Merge "Apply IDumpstateListener changes"
diff --git a/Android.bp b/Android.bp
index 69ee848..82a972a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -257,6 +257,7 @@
"core/java/android/service/euicc/IGetEuiccInfoCallback.aidl",
"core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl",
"core/java/android/service/euicc/IGetOtaStatusCallback.aidl",
+ "core/java/android/service/euicc/IOtaStatusChangedCallback.aidl",
"core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl",
"core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
"core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
@@ -617,6 +618,7 @@
"android.hardware.vibrator-V1.0-java-constants",
"android.hardware.vibrator-V1.1-java-constants",
"android.hardware.wifi-V1.0-java-constants",
+ "android.hardware.radio-V1.0-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
@@ -730,10 +732,18 @@
"core/proto/android/os/procrank.proto",
"core/proto/android/os/ps.proto",
"core/proto/android/os/system_properties.proto",
+ "core/proto/android/util/event_log_tags.proto",
],
// Append protoc-gen-cppstream tool's PATH otherwise aprotoc can't find the plugin tool
- cmd: "PATH=$$PATH:$$(dirname $(location protoc-gen-cppstream)) $(location aprotoc) --plugin=protoc-gen-cpp-stream=$(location protoc-gen-cppstream) --dependency_out=$(depfile) --cppstream_out=$(genDir)/ -Iexternal/protobuf/src -I . $(in)",
+ cmd: "mkdir -p $(genDir) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-cppstream) " +
+ " --dependency_out=$(depfile) " +
+ " --cppstream_out=$(genDir) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in)",
output_extension = "proto.h",
}
diff --git a/Android.mk b/Android.mk
index 8199c57..3c6dd37 100644
--- a/Android.mk
+++ b/Android.mk
@@ -829,4 +829,4 @@
include $(call first-makefiles-under,$(LOCAL_PATH))
endif
-endif # ANDROID_BUILD_EMBEDDED
+endif # ANDROID_BUILD_EMBEDDED
\ No newline at end of file
diff --git a/api/current.txt b/api/current.txt
index d8deef3..484ca48 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -579,6 +579,7 @@
field public static final int fadingEdge = 16842975; // 0x10100df
field public static final int fadingEdgeLength = 16842976; // 0x10100e0
field public static final int fadingMode = 16843745; // 0x10103e1
+ field public static final int fallbackLineSpacing = 16844155; // 0x101057b
field public static final int fastScrollAlwaysVisible = 16843573; // 0x1010335
field public static final int fastScrollEnabled = 16843302; // 0x1010226
field public static final int fastScrollOverlayPosition = 16843578; // 0x101033a
@@ -5205,15 +5206,17 @@
field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
+ field public static final java.lang.String EXTRA_MESSAGING_PERSON = "android.messagingUser";
field public static final java.lang.String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
field public static final java.lang.String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
- field public static final java.lang.String EXTRA_PEOPLE = "android.people";
+ field public static final deprecated java.lang.String EXTRA_PEOPLE = "android.people";
+ field public static final java.lang.String EXTRA_PEOPLE_LIST = "android.people.list";
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
- field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+ field public static final deprecated java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
field public static final deprecated java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -5353,7 +5356,8 @@
method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
- method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public deprecated android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder addPerson(android.app.Notification.Person);
method public android.app.Notification build();
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
@@ -5476,14 +5480,17 @@
}
public static class Notification.MessagingStyle extends android.app.Notification.Style {
- ctor public Notification.MessagingStyle(java.lang.CharSequence);
+ ctor public deprecated Notification.MessagingStyle(java.lang.CharSequence);
+ ctor public Notification.MessagingStyle(android.app.Notification.Person);
method public android.app.Notification.MessagingStyle addHistoricMessage(android.app.Notification.MessagingStyle.Message);
- method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public deprecated android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, android.app.Notification.Person);
method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
method public java.lang.CharSequence getConversationTitle();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getHistoricMessages();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
- method public java.lang.CharSequence getUserDisplayName();
+ method public android.app.Notification.Person getUser();
+ method public deprecated java.lang.CharSequence getUserDisplayName();
method public boolean isGroupConversation();
method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
method public android.app.Notification.MessagingStyle setGroupConversation(boolean);
@@ -5491,16 +5498,34 @@
}
public static final class Notification.MessagingStyle.Message {
- ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ ctor public deprecated Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, android.app.Notification.Person);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
method public android.os.Bundle getExtras();
- method public java.lang.CharSequence getSender();
+ method public deprecated java.lang.CharSequence getSender();
+ method public android.app.Notification.Person getSenderPerson();
method public java.lang.CharSequence getText();
method public long getTimestamp();
method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
}
+ public static final class Notification.Person implements android.os.Parcelable {
+ ctor protected Notification.Person(android.os.Parcel);
+ ctor public Notification.Person();
+ method public int describeContents();
+ method public android.graphics.drawable.Icon getIcon();
+ method public java.lang.String getKey();
+ method public java.lang.CharSequence getName();
+ method public java.lang.String getUri();
+ method public android.app.Notification.Person setIcon(android.graphics.drawable.Icon);
+ method public android.app.Notification.Person setKey(java.lang.String);
+ method public android.app.Notification.Person setName(java.lang.CharSequence);
+ method public android.app.Notification.Person setUri(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.Person> CREATOR;
+ }
+
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
@@ -6297,6 +6322,7 @@
method public void onReceive(android.content.Context, android.content.Intent);
method public void onSecurityLogsAvailable(android.content.Context, android.content.Intent);
method public void onSystemUpdatePending(android.content.Context, android.content.Intent, long);
+ method public void onTransferOwnershipComplete(android.content.Context, android.os.PersistableBundle);
method public void onUserAdded(android.content.Context, android.content.Intent, android.os.UserHandle);
method public void onUserRemoved(android.content.Context, android.content.Intent, android.os.UserHandle);
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
@@ -6314,6 +6340,7 @@
field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
+ field public static final java.lang.String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
}
public class DeviceAdminService extends android.app.Service {
@@ -6506,6 +6533,7 @@
method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
method public boolean stopUser(android.content.ComponentName, android.os.UserHandle);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
+ method public void transferOwnership(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
method public void wipeData(int);
@@ -6515,6 +6543,7 @@
field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+ field public static final java.lang.String ACTION_PROFILE_OWNER_CHANGED = "android.app.action.PROFILE_OWNER_CHANGED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
@@ -7361,6 +7390,7 @@
method public void updateAppWidget(int, android.widget.RemoteViews);
method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
method public void updateAppWidgetOptions(int, android.os.Bundle);
+ method public void updateAppWidgetProviderInfo(android.content.ComponentName, java.lang.String);
field public static final java.lang.String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
field public static final java.lang.String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
field public static final java.lang.String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
@@ -9339,6 +9369,7 @@
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
+ field public static final java.lang.String WIFI_RTT_RANGING_SERVICE = "wifirtt";
field public static final java.lang.String WIFI_SERVICE = "wifi";
field public static final java.lang.String WINDOW_SERVICE = "window";
}
@@ -11121,6 +11152,7 @@
field public static final java.lang.String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
field public static final java.lang.String FEATURE_WIFI_PASSPOINT = "android.hardware.wifi.passpoint";
+ field public static final java.lang.String FEATURE_WIFI_RTT = "android.hardware.wifi.rtt";
field public static final int GET_ACTIVITIES = 1; // 0x1
field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
field public static final deprecated int GET_DISABLED_COMPONENTS = 512; // 0x200
@@ -11351,6 +11383,7 @@
field public static final int DISABLED_REASON_NOT_DISABLED = 0; // 0x0
field public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103; // 0x67
field public static final int DISABLED_REASON_SIGNATURE_MISMATCH = 102; // 0x66
+ field public static final int DISABLED_REASON_UNKNOWN = 3; // 0x3
field public static final int DISABLED_REASON_VERSION_LOWER = 100; // 0x64
field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
@@ -15530,6 +15563,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_HYPERFOCAL_DISTANCE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_INTRINSIC_CALIBRATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> LENS_POSE_REFERENCE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_ROTATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_TRANSLATION;
field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_RADIAL_DISTORTION;
@@ -15602,6 +15636,8 @@
method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract java.lang.String getId();
field public static final int TEMPLATE_MANUAL = 6; // 0x6
+ field public static final int TEMPLATE_MOTION_TRACKING_BEST = 8; // 0x8
+ field public static final int TEMPLATE_MOTION_TRACKING_PREVIEW = 7; // 0x7
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
field public static final int TEMPLATE_RECORD = 3; // 0x3
field public static final int TEMPLATE_STILL_CAPTURE = 2; // 0x2
@@ -15704,6 +15740,7 @@
field public static final int CONTROL_AWB_STATE_SEARCHING = 1; // 0x1
field public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0; // 0x0
field public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; // 0x6
+ field public static final int CONTROL_CAPTURE_INTENT_MOTION_TRACKING = 7; // 0x7
field public static final int CONTROL_CAPTURE_INTENT_PREVIEW = 1; // 0x1
field public static final int CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2; // 0x2
field public static final int CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3; // 0x3
@@ -15770,6 +15807,8 @@
field public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED = 0; // 0x0
field public static final int LENS_OPTICAL_STABILIZATION_MODE_OFF = 0; // 0x0
field public static final int LENS_OPTICAL_STABILIZATION_MODE_ON = 1; // 0x1
+ field public static final int LENS_POSE_REFERENCE_GYROSCOPE = 1; // 0x1
+ field public static final int LENS_POSE_REFERENCE_PRIMARY_CAMERA = 0; // 0x0
field public static final int LENS_STATE_MOVING = 1; // 0x1
field public static final int LENS_STATE_STATIONARY = 0; // 0x0
field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
@@ -15783,6 +15822,7 @@
field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10; // 0xa
field public static final int REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING = 4; // 0x4
field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
@@ -20180,6 +20220,13 @@
ctor public ICUUncheckedIOException(java.lang.String, java.lang.Throwable);
}
+ public class IllformedLocaleException extends java.lang.RuntimeException {
+ ctor public IllformedLocaleException();
+ ctor public IllformedLocaleException(java.lang.String);
+ ctor public IllformedLocaleException(java.lang.String, int);
+ method public int getErrorIndex();
+ }
+
public class IndianCalendar extends android.icu.util.Calendar {
ctor public IndianCalendar();
ctor public IndianCalendar(android.icu.util.TimeZone);
@@ -20264,6 +20311,32 @@
field public static final int TAISHO;
}
+ public final class LocaleData {
+ method public static android.icu.util.VersionInfo getCLDRVersion();
+ method public java.lang.String getDelimiter(int);
+ method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
+ method public static final android.icu.util.LocaleData getInstance();
+ method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
+ method public boolean getNoSubstitute();
+ method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
+ method public void setNoSubstitute(boolean);
+ field public static final int ALT_QUOTATION_END = 3; // 0x3
+ field public static final int ALT_QUOTATION_START = 2; // 0x2
+ field public static final int QUOTATION_END = 1; // 0x1
+ field public static final int QUOTATION_START = 0; // 0x0
+ }
+
+ public static final class LocaleData.MeasurementSystem {
+ field public static final android.icu.util.LocaleData.MeasurementSystem SI;
+ field public static final android.icu.util.LocaleData.MeasurementSystem UK;
+ field public static final android.icu.util.LocaleData.MeasurementSystem US;
+ }
+
+ public static final class LocaleData.PaperSize {
+ method public int getHeight();
+ method public int getWidth();
+ }
+
public class Measure {
ctor public Measure(java.lang.Number, android.icu.util.MeasureUnit);
method public java.lang.Number getNumber();
@@ -23137,6 +23210,7 @@
field public static final java.lang.String KEY_MAX_WIDTH = "max-width";
field public static final java.lang.String KEY_MIME = "mime";
field public static final java.lang.String KEY_OPERATING_RATE = "operating-rate";
+ field public static final java.lang.String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth";
field public static final java.lang.String KEY_PCM_ENCODING = "pcm-encoding";
field public static final java.lang.String KEY_PRIORITY = "priority";
field public static final java.lang.String KEY_PROFILE = "profile";
@@ -27267,13 +27341,13 @@
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
- method public boolean startScan();
+ method public deprecated boolean startScan();
method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
method public int updateNetwork(android.net.wifi.WifiConfiguration);
field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
- field public static final java.lang.String EXTRA_BSSID = "bssid";
+ field public static final deprecated java.lang.String EXTRA_BSSID = "bssid";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
@@ -27281,7 +27355,7 @@
field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
- field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
+ field public static final deprecated java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -27780,6 +27854,55 @@
}
+package android.net.wifi.rtt {
+
+ public final class RangingRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getMaxPeers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR;
+ }
+
+ public static final class RangingRequest.Builder {
+ ctor public RangingRequest.Builder();
+ method public android.net.wifi.rtt.RangingRequest.Builder addAccessPoint(android.net.wifi.ScanResult);
+ method public android.net.wifi.rtt.RangingRequest.Builder addAccessPoints(java.util.List<android.net.wifi.ScanResult>);
+ method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(android.net.MacAddress);
+ method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(android.net.wifi.aware.PeerHandle);
+ method public android.net.wifi.rtt.RangingRequest build();
+ }
+
+ public final class RangingResult implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDistanceMm();
+ method public int getDistanceStdDevMm();
+ method public android.net.MacAddress getMacAddress();
+ method public android.net.wifi.aware.PeerHandle getPeerHandle();
+ method public long getRangingTimestampUs();
+ method public int getRssi();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingResult> CREATOR;
+ field public static final int STATUS_FAIL = 1; // 0x1
+ field public static final int STATUS_SUCCESS = 0; // 0x0
+ }
+
+ public abstract class RangingResultCallback {
+ ctor public RangingResultCallback();
+ method public abstract void onRangingFailure(int);
+ method public abstract void onRangingResults(java.util.List<android.net.wifi.rtt.RangingResult>);
+ field public static final int STATUS_CODE_FAIL = 1; // 0x1
+ field public static final int STATUS_CODE_FAIL_RTT_NOT_AVAILABLE = 2; // 0x2
+ }
+
+ public class WifiRttManager {
+ method public boolean isAvailable();
+ method public void startRanging(android.net.wifi.rtt.RangingRequest, android.net.wifi.rtt.RangingResultCallback, android.os.Handler);
+ field public static final java.lang.String ACTION_WIFI_RTT_STATE_CHANGED = "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
+ }
+
+}
+
package android.nfc {
public class FormatException extends java.lang.Exception {
@@ -35958,7 +36081,7 @@
public static final class Telephony.Carriers implements android.provider.BaseColumns {
field public static final java.lang.String APN = "apn";
field public static final java.lang.String AUTH_TYPE = "authtype";
- field public static final java.lang.String BEARER = "bearer";
+ field public static final deprecated java.lang.String BEARER = "bearer";
field public static final java.lang.String CARRIER_ENABLED = "carrier_enabled";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String CURRENT = "current";
@@ -35971,6 +36094,7 @@
field public static final java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
field public static final java.lang.String MVNO_TYPE = "mvno_type";
field public static final java.lang.String NAME = "name";
+ field public static final java.lang.String NETWORK_TYPE_BITMASK = "network_type_bitmask";
field public static final java.lang.String NUMERIC = "numeric";
field public static final java.lang.String PASSWORD = "password";
field public static final java.lang.String PORT = "port";
@@ -36284,6 +36408,7 @@
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
field public static final java.lang.String LAST_MODIFIED = "last_modified";
field public static final java.lang.String MIME_TYPE = "mime_type";
+ field public static final java.lang.String NEW = "new";
field public static final java.lang.String NUMBER = "number";
field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
@@ -37934,6 +38059,7 @@
public class CarrierIdentifier implements android.os.Parcelable {
ctor public CarrierIdentifier(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ ctor public CarrierIdentifier(byte[], java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String getGid1();
method public java.lang.String getGid2();
@@ -40380,6 +40506,113 @@
package android.telephony {
+ public final class AccessNetworkConstants {
+ ctor public AccessNetworkConstants();
+ }
+
+ public static final class AccessNetworkConstants.AccessNetworkType {
+ ctor public AccessNetworkConstants.AccessNetworkType();
+ field public static final int CDMA2000 = 4; // 0x4
+ field public static final int EUTRAN = 3; // 0x3
+ field public static final int GERAN = 1; // 0x1
+ field public static final int IWLAN = 5; // 0x5
+ field public static final int UTRAN = 2; // 0x2
+ }
+
+ public static final class AccessNetworkConstants.EutranBand {
+ ctor public AccessNetworkConstants.EutranBand();
+ field public static final int BAND_1 = 1; // 0x1
+ field public static final int BAND_10 = 10; // 0xa
+ field public static final int BAND_11 = 11; // 0xb
+ field public static final int BAND_12 = 12; // 0xc
+ field public static final int BAND_13 = 13; // 0xd
+ field public static final int BAND_14 = 14; // 0xe
+ field public static final int BAND_17 = 17; // 0x11
+ field public static final int BAND_18 = 18; // 0x12
+ field public static final int BAND_19 = 19; // 0x13
+ field public static final int BAND_2 = 2; // 0x2
+ field public static final int BAND_20 = 20; // 0x14
+ field public static final int BAND_21 = 21; // 0x15
+ field public static final int BAND_22 = 22; // 0x16
+ field public static final int BAND_23 = 23; // 0x17
+ field public static final int BAND_24 = 24; // 0x18
+ field public static final int BAND_25 = 25; // 0x19
+ field public static final int BAND_26 = 26; // 0x1a
+ field public static final int BAND_27 = 27; // 0x1b
+ field public static final int BAND_28 = 28; // 0x1c
+ field public static final int BAND_3 = 3; // 0x3
+ field public static final int BAND_30 = 30; // 0x1e
+ field public static final int BAND_31 = 31; // 0x1f
+ field public static final int BAND_33 = 33; // 0x21
+ field public static final int BAND_34 = 34; // 0x22
+ field public static final int BAND_35 = 35; // 0x23
+ field public static final int BAND_36 = 36; // 0x24
+ field public static final int BAND_37 = 37; // 0x25
+ field public static final int BAND_38 = 38; // 0x26
+ field public static final int BAND_39 = 39; // 0x27
+ field public static final int BAND_4 = 4; // 0x4
+ field public static final int BAND_40 = 40; // 0x28
+ field public static final int BAND_41 = 41; // 0x29
+ field public static final int BAND_42 = 42; // 0x2a
+ field public static final int BAND_43 = 43; // 0x2b
+ field public static final int BAND_44 = 44; // 0x2c
+ field public static final int BAND_45 = 45; // 0x2d
+ field public static final int BAND_46 = 46; // 0x2e
+ field public static final int BAND_47 = 47; // 0x2f
+ field public static final int BAND_48 = 48; // 0x30
+ field public static final int BAND_5 = 5; // 0x5
+ field public static final int BAND_6 = 6; // 0x6
+ field public static final int BAND_65 = 65; // 0x41
+ field public static final int BAND_66 = 66; // 0x42
+ field public static final int BAND_68 = 68; // 0x44
+ field public static final int BAND_7 = 7; // 0x7
+ field public static final int BAND_70 = 70; // 0x46
+ field public static final int BAND_8 = 8; // 0x8
+ field public static final int BAND_9 = 9; // 0x9
+ }
+
+ public static final class AccessNetworkConstants.GeranBand {
+ ctor public AccessNetworkConstants.GeranBand();
+ field public static final int BAND_450 = 3; // 0x3
+ field public static final int BAND_480 = 4; // 0x4
+ field public static final int BAND_710 = 5; // 0x5
+ field public static final int BAND_750 = 6; // 0x6
+ field public static final int BAND_850 = 8; // 0x8
+ field public static final int BAND_DCS1800 = 12; // 0xc
+ field public static final int BAND_E900 = 10; // 0xa
+ field public static final int BAND_ER900 = 14; // 0xe
+ field public static final int BAND_P900 = 9; // 0x9
+ field public static final int BAND_PCS1900 = 13; // 0xd
+ field public static final int BAND_R900 = 11; // 0xb
+ field public static final int BAND_T380 = 1; // 0x1
+ field public static final int BAND_T410 = 2; // 0x2
+ field public static final int BAND_T810 = 7; // 0x7
+ }
+
+ public static final class AccessNetworkConstants.UtranBand {
+ ctor public AccessNetworkConstants.UtranBand();
+ field public static final int BAND_1 = 1; // 0x1
+ field public static final int BAND_10 = 10; // 0xa
+ field public static final int BAND_11 = 11; // 0xb
+ field public static final int BAND_12 = 12; // 0xc
+ field public static final int BAND_13 = 13; // 0xd
+ field public static final int BAND_14 = 14; // 0xe
+ field public static final int BAND_19 = 19; // 0x13
+ field public static final int BAND_2 = 2; // 0x2
+ field public static final int BAND_20 = 20; // 0x14
+ field public static final int BAND_21 = 21; // 0x15
+ field public static final int BAND_22 = 22; // 0x16
+ field public static final int BAND_25 = 25; // 0x19
+ field public static final int BAND_26 = 26; // 0x1a
+ field public static final int BAND_3 = 3; // 0x3
+ field public static final int BAND_4 = 4; // 0x4
+ field public static final int BAND_5 = 5; // 0x5
+ field public static final int BAND_6 = 6; // 0x6
+ field public static final int BAND_7 = 7; // 0x7
+ field public static final int BAND_8 = 8; // 0x8
+ field public static final int BAND_9 = 9; // 0x9
+ }
+
public class CarrierConfigManager {
method public android.os.PersistableBundle getConfig();
method public android.os.PersistableBundle getConfigForSubId(int);
@@ -40531,8 +40764,13 @@
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
- public final class CellIdentityCdma implements android.os.Parcelable {
+ public abstract class CellIdentity implements android.os.Parcelable {
method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentity> CREATOR;
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
method public int getBasestationId();
method public int getLatitude();
method public int getLongitude();
@@ -40544,8 +40782,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityCdma> CREATOR;
}
- public final class CellIdentityGsm implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
method public int getArfcn();
method public int getBsic();
method public int getCid();
@@ -40562,8 +40799,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityGsm> CREATOR;
}
- public final class CellIdentityLte implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
method public int getCi();
method public int getEarfcn();
method public deprecated int getMcc();
@@ -40579,8 +40815,17 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR;
}
- public final class CellIdentityWcdma implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method public int getCid();
+ method public int getCpid();
+ method public int getLac();
+ method public java.lang.String getMccStr();
+ method public java.lang.String getMncStr();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
method public int getCid();
method public int getLac();
method public deprecated int getMcc();
@@ -40904,111 +41149,6 @@
field public static final android.os.Parcelable.Creator<android.telephony.RadioAccessSpecifier> CREATOR;
}
- public final class RadioNetworkConstants {
- ctor public RadioNetworkConstants();
- }
-
- public static final class RadioNetworkConstants.EutranBands {
- ctor public RadioNetworkConstants.EutranBands();
- field public static final int BAND_1 = 1; // 0x1
- field public static final int BAND_10 = 10; // 0xa
- field public static final int BAND_11 = 11; // 0xb
- field public static final int BAND_12 = 12; // 0xc
- field public static final int BAND_13 = 13; // 0xd
- field public static final int BAND_14 = 14; // 0xe
- field public static final int BAND_17 = 17; // 0x11
- field public static final int BAND_18 = 18; // 0x12
- field public static final int BAND_19 = 19; // 0x13
- field public static final int BAND_2 = 2; // 0x2
- field public static final int BAND_20 = 20; // 0x14
- field public static final int BAND_21 = 21; // 0x15
- field public static final int BAND_22 = 22; // 0x16
- field public static final int BAND_23 = 23; // 0x17
- field public static final int BAND_24 = 24; // 0x18
- field public static final int BAND_25 = 25; // 0x19
- field public static final int BAND_26 = 26; // 0x1a
- field public static final int BAND_27 = 27; // 0x1b
- field public static final int BAND_28 = 28; // 0x1c
- field public static final int BAND_3 = 3; // 0x3
- field public static final int BAND_30 = 30; // 0x1e
- field public static final int BAND_31 = 31; // 0x1f
- field public static final int BAND_33 = 33; // 0x21
- field public static final int BAND_34 = 34; // 0x22
- field public static final int BAND_35 = 35; // 0x23
- field public static final int BAND_36 = 36; // 0x24
- field public static final int BAND_37 = 37; // 0x25
- field public static final int BAND_38 = 38; // 0x26
- field public static final int BAND_39 = 39; // 0x27
- field public static final int BAND_4 = 4; // 0x4
- field public static final int BAND_40 = 40; // 0x28
- field public static final int BAND_41 = 41; // 0x29
- field public static final int BAND_42 = 42; // 0x2a
- field public static final int BAND_43 = 43; // 0x2b
- field public static final int BAND_44 = 44; // 0x2c
- field public static final int BAND_45 = 45; // 0x2d
- field public static final int BAND_46 = 46; // 0x2e
- field public static final int BAND_47 = 47; // 0x2f
- field public static final int BAND_48 = 48; // 0x30
- field public static final int BAND_5 = 5; // 0x5
- field public static final int BAND_6 = 6; // 0x6
- field public static final int BAND_65 = 65; // 0x41
- field public static final int BAND_66 = 66; // 0x42
- field public static final int BAND_68 = 68; // 0x44
- field public static final int BAND_7 = 7; // 0x7
- field public static final int BAND_70 = 70; // 0x46
- field public static final int BAND_8 = 8; // 0x8
- field public static final int BAND_9 = 9; // 0x9
- }
-
- public static final class RadioNetworkConstants.GeranBands {
- ctor public RadioNetworkConstants.GeranBands();
- field public static final int BAND_450 = 3; // 0x3
- field public static final int BAND_480 = 4; // 0x4
- field public static final int BAND_710 = 5; // 0x5
- field public static final int BAND_750 = 6; // 0x6
- field public static final int BAND_850 = 8; // 0x8
- field public static final int BAND_DCS1800 = 12; // 0xc
- field public static final int BAND_E900 = 10; // 0xa
- field public static final int BAND_ER900 = 14; // 0xe
- field public static final int BAND_P900 = 9; // 0x9
- field public static final int BAND_PCS1900 = 13; // 0xd
- field public static final int BAND_R900 = 11; // 0xb
- field public static final int BAND_T380 = 1; // 0x1
- field public static final int BAND_T410 = 2; // 0x2
- field public static final int BAND_T810 = 7; // 0x7
- }
-
- public static final class RadioNetworkConstants.RadioAccessNetworks {
- ctor public RadioNetworkConstants.RadioAccessNetworks();
- field public static final int EUTRAN = 3; // 0x3
- field public static final int GERAN = 1; // 0x1
- field public static final int UTRAN = 2; // 0x2
- }
-
- public static final class RadioNetworkConstants.UtranBands {
- ctor public RadioNetworkConstants.UtranBands();
- field public static final int BAND_1 = 1; // 0x1
- field public static final int BAND_10 = 10; // 0xa
- field public static final int BAND_11 = 11; // 0xb
- field public static final int BAND_12 = 12; // 0xc
- field public static final int BAND_13 = 13; // 0xd
- field public static final int BAND_14 = 14; // 0xe
- field public static final int BAND_19 = 19; // 0x13
- field public static final int BAND_2 = 2; // 0x2
- field public static final int BAND_20 = 20; // 0x14
- field public static final int BAND_21 = 21; // 0x15
- field public static final int BAND_22 = 22; // 0x16
- field public static final int BAND_25 = 25; // 0x19
- field public static final int BAND_26 = 26; // 0x1a
- field public static final int BAND_3 = 3; // 0x3
- field public static final int BAND_4 = 4; // 0x4
- field public static final int BAND_5 = 5; // 0x5
- field public static final int BAND_6 = 6; // 0x6
- field public static final int BAND_7 = 7; // 0x7
- field public static final int BAND_8 = 8; // 0x8
- field public static final int BAND_9 = 9; // 0x9
- }
-
public class ServiceState implements android.os.Parcelable {
ctor public ServiceState();
ctor public ServiceState(android.telephony.ServiceState);
@@ -41016,11 +41156,13 @@
method protected void copyFrom(android.telephony.ServiceState);
method public int describeContents();
method public boolean getIsManualSelection();
+ method public int getNetworkId();
method public java.lang.String getOperatorAlphaLong();
method public java.lang.String getOperatorAlphaShort();
method public java.lang.String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
+ method public int getSystemId();
method public void setIsManualSelection(boolean);
method public void setOperatorName(java.lang.String, java.lang.String, java.lang.String);
method public void setRoaming(boolean);
@@ -41033,6 +41175,7 @@
field public static final int STATE_IN_SERVICE = 0; // 0x0
field public static final int STATE_OUT_OF_SERVICE = 1; // 0x1
field public static final int STATE_POWER_OFF = 3; // 0x3
+ field public static final int UNKNOWN_ID = -1; // 0xffffffff
}
public class SignalStrength implements android.os.Parcelable {
@@ -41474,6 +41617,78 @@
}
+package android.telephony.data {
+
+ public class ApnSetting implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getApnName();
+ method public int getAuthType();
+ method public java.lang.String getEntryName();
+ method public int getId();
+ method public int getMmsPort();
+ method public java.net.InetAddress getMmsProxy();
+ method public java.net.URL getMmsc();
+ method public java.lang.String getMvnoType();
+ method public java.lang.String getOperatorNumeric();
+ method public java.lang.String getPassword();
+ method public int getPort();
+ method public java.lang.String getProtocol();
+ method public java.net.InetAddress getProxy();
+ method public java.lang.String getRoamingProtocol();
+ method public java.util.List<java.lang.String> getTypes();
+ method public java.lang.String getUser();
+ method public boolean isEnabled();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUTH_TYPE_CHAP = 2; // 0x2
+ field public static final int AUTH_TYPE_NONE = 0; // 0x0
+ field public static final int AUTH_TYPE_PAP = 1; // 0x1
+ field public static final int AUTH_TYPE_PAP_OR_CHAP = 3; // 0x3
+ field public static final android.os.Parcelable.Creator<android.telephony.data.ApnSetting> CREATOR;
+ field public static final java.lang.String MVNO_TYPE_GID = "gid";
+ field public static final java.lang.String MVNO_TYPE_ICCID = "iccid";
+ field public static final java.lang.String MVNO_TYPE_IMSI = "imsi";
+ field public static final java.lang.String MVNO_TYPE_SPN = "spn";
+ field public static final java.lang.String PROTOCOL_IP = "IP";
+ field public static final java.lang.String PROTOCOL_IPV4V6 = "IPV4V6";
+ field public static final java.lang.String PROTOCOL_IPV6 = "IPV6";
+ field public static final java.lang.String PROTOCOL_PPP = "PPP";
+ field public static final java.lang.String TYPE_ALL = "*";
+ field public static final java.lang.String TYPE_CBS = "cbs";
+ field public static final java.lang.String TYPE_DEFAULT = "default";
+ field public static final java.lang.String TYPE_DUN = "dun";
+ field public static final java.lang.String TYPE_EMERGENCY = "emergency";
+ field public static final java.lang.String TYPE_FOTA = "fota";
+ field public static final java.lang.String TYPE_HIPRI = "hipri";
+ field public static final java.lang.String TYPE_IA = "ia";
+ field public static final java.lang.String TYPE_IMS = "ims";
+ field public static final java.lang.String TYPE_MMS = "mms";
+ field public static final java.lang.String TYPE_SUPL = "supl";
+ }
+
+ public static class ApnSetting.Builder {
+ ctor public ApnSetting.Builder();
+ method public android.telephony.data.ApnSetting build();
+ method public android.telephony.data.ApnSetting.Builder setApnName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setAuthType(int);
+ method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+ method public android.telephony.data.ApnSetting.Builder setEntryName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setId(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsPort(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setMmsc(java.net.URL);
+ method public android.telephony.data.ApnSetting.Builder setMvnoType(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPassword(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPort(int);
+ method public android.telephony.data.ApnSetting.Builder setProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setTypes(java.util.List<java.lang.String>);
+ method public android.telephony.data.ApnSetting.Builder setUser(java.lang.String);
+ }
+
+}
+
package android.telephony.gsm {
public class GsmCellLocation extends android.telephony.CellLocation {
@@ -52310,6 +52525,7 @@
method public boolean isAllCaps();
method public boolean isCursorVisible();
method public boolean isElegantTextHeight();
+ method public boolean isFallbackLineSpacing();
method public boolean isInputMethodTarget();
method public boolean isSuggestionsEnabled();
method public boolean isTextSelectable();
@@ -52353,6 +52569,7 @@
method public void setError(java.lang.CharSequence);
method public void setError(java.lang.CharSequence, android.graphics.drawable.Drawable);
method public void setExtractedText(android.view.inputmethod.ExtractedText);
+ method public void setFallbackLineSpacing(boolean);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
method public boolean setFontVariationSettings(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index ba1d383..979c38b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -137,6 +137,7 @@
field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
field public static final java.lang.String RECEIVE_WIFI_CREDENTIAL_CHANGE = "android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE";
field public static final java.lang.String RECOVERY = "android.permission.RECOVERY";
+ field public static final java.lang.String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE";
field public static final java.lang.String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
@@ -173,6 +174,7 @@
field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK";
field public static final java.lang.String UPDATE_TIME_ZONE_RULES = "android.permission.UPDATE_TIME_ZONE_RULES";
field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
+ field public static final java.lang.String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK";
field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
field public static final java.lang.String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE";
field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
@@ -313,6 +315,10 @@
method public void onInstantAppResolveInfo(java.util.List<android.content.pm.InstantAppResolveInfo>);
}
+ public class KeyguardManager {
+ method public android.content.Intent createConfirmFactoryResetCredentialIntent(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+ }
+
public class Notification implements android.os.Parcelable {
field public static final java.lang.String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup";
field public static final java.lang.String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
@@ -1448,7 +1454,7 @@
method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage);
}
- public class ContextHubMessage {
+ public deprecated class ContextHubMessage {
ctor public ContextHubMessage(int, int, byte[]);
method public int describeContents();
method public byte[] getData();
@@ -1579,7 +1585,7 @@
field public static final android.os.Parcelable.Creator<android.hardware.location.MemoryRegion> CREATOR;
}
- public class NanoApp {
+ public deprecated class NanoApp {
ctor public NanoApp();
ctor public deprecated NanoApp(int, byte[]);
ctor public NanoApp(long, byte[]);
@@ -1627,7 +1633,7 @@
field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppBinary> CREATOR;
}
- public class NanoAppFilter {
+ public deprecated class NanoAppFilter {
ctor public NanoAppFilter(long, int, int, long);
method public int describeContents();
method public boolean testMatch(android.hardware.location.NanoAppInstanceInfo);
@@ -1642,7 +1648,7 @@
field public static final int VENDOR_ANY = -1; // 0xffffffff
}
- public class NanoAppInstanceInfo {
+ public deprecated class NanoAppInstanceInfo {
ctor public NanoAppInstanceInfo();
method public int describeContents();
method public long getAppId();
@@ -1751,6 +1757,15 @@
field public static final int CLASS_AM_FM = 0; // 0x0
field public static final int CLASS_DT = 2; // 0x2
field public static final int CLASS_SAT = 1; // 0x1
+ field public static final int CONFIG_DAB_DAB_LINKING = 6; // 0x6
+ field public static final int CONFIG_DAB_DAB_SOFT_LINKING = 8; // 0x8
+ field public static final int CONFIG_DAB_FM_LINKING = 7; // 0x7
+ field public static final int CONFIG_DAB_FM_SOFT_LINKING = 9; // 0x9
+ field public static final int CONFIG_FORCE_ANALOG = 2; // 0x2
+ field public static final int CONFIG_FORCE_DIGITAL = 3; // 0x3
+ field public static final int CONFIG_FORCE_MONO = 1; // 0x1
+ field public static final int CONFIG_RDS_AF = 4; // 0x4
+ field public static final int CONFIG_RDS_REG = 5; // 0x5
field public static final int REGION_ITU_1 = 0; // 0x0
field public static final int REGION_ITU_2 = 1; // 0x1
field public static final int REGION_JAPAN = 3; // 0x3
@@ -1930,15 +1945,20 @@
method public abstract void close();
method public abstract int getConfiguration(android.hardware.radio.RadioManager.BandConfig[]);
method public abstract boolean getMute();
+ method public java.util.Map<java.lang.String, java.lang.String> getParameters(java.util.List<java.lang.String>);
method public abstract int getProgramInformation(android.hardware.radio.RadioManager.ProgramInfo[]);
method public abstract java.util.List<android.hardware.radio.RadioManager.ProgramInfo> getProgramList(java.util.Map<java.lang.String, java.lang.String>);
method public abstract boolean hasControl();
- method public abstract boolean isAnalogForced();
+ method public abstract deprecated boolean isAnalogForced();
method public abstract boolean isAntennaConnected();
+ method public boolean isConfigFlagSet(int);
+ method public boolean isConfigFlagSupported(int);
method public abstract int scan(int, boolean);
- method public abstract void setAnalogForced(boolean);
+ method public abstract deprecated void setAnalogForced(boolean);
+ method public void setConfigFlag(int, boolean);
method public abstract int setConfiguration(android.hardware.radio.RadioManager.BandConfig);
method public abstract int setMute(boolean);
+ method public java.util.Map<java.lang.String, java.lang.String> setParameters(java.util.Map<java.lang.String, java.lang.String>);
method public abstract boolean startBackgroundScan();
method public abstract int step(int, boolean);
method public abstract deprecated int tune(int, int);
@@ -1964,6 +1984,7 @@
method public void onEmergencyAnnouncement(boolean);
method public void onError(int);
method public deprecated void onMetadataChanged(android.hardware.radio.RadioMetadata);
+ method public void onParametersUpdated(java.util.Map<java.lang.String, java.lang.String>);
method public void onProgramInfoChanged(android.hardware.radio.RadioManager.ProgramInfo);
method public void onProgramListChanged();
method public void onTrafficAnnouncement(boolean);
@@ -3256,6 +3277,52 @@
}
+package android.net.wifi.rtt {
+
+ public static final class RangingRequest.Builder {
+ method public android.net.wifi.rtt.RangingRequest.Builder addResponder(android.net.wifi.rtt.ResponderConfig);
+ }
+
+ public final class ResponderConfig implements android.os.Parcelable {
+ ctor public ResponderConfig(android.net.MacAddress, int, boolean, int, int, int, int, int);
+ ctor public ResponderConfig(android.net.wifi.aware.PeerHandle, int, boolean, int, int, int, int, int);
+ method public int describeContents();
+ method public static android.net.wifi.rtt.ResponderConfig fromScanResult(android.net.wifi.ScanResult);
+ method public static android.net.wifi.rtt.ResponderConfig fromWifiAwarePeerHandleWithDefaults(android.net.wifi.aware.PeerHandle);
+ method public static android.net.wifi.rtt.ResponderConfig fromWifiAwarePeerMacAddressWithDefaults(android.net.MacAddress);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+ field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
+ field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.ResponderConfig> CREATOR;
+ field public static final int PREAMBLE_HT = 1; // 0x1
+ field public static final int PREAMBLE_LEGACY = 0; // 0x0
+ field public static final int PREAMBLE_VHT = 2; // 0x2
+ field public static final int RESPONDER_AP = 0; // 0x0
+ field public static final int RESPONDER_AWARE = 4; // 0x4
+ field public static final int RESPONDER_P2P_CLIENT = 3; // 0x3
+ field public static final int RESPONDER_P2P_GO = 2; // 0x2
+ field public static final int RESPONDER_STA = 1; // 0x1
+ field public final int centerFreq0;
+ field public final int centerFreq1;
+ field public final int channelWidth;
+ field public final int frequency;
+ field public final android.net.MacAddress macAddress;
+ field public final android.net.wifi.aware.PeerHandle peerHandle;
+ field public final int preamble;
+ field public final int responderType;
+ field public final boolean supports80211mc;
+ }
+
+ public class WifiRttManager {
+ method public void cancelRanging(android.os.WorkSource);
+ method public void startRanging(android.os.WorkSource, android.net.wifi.rtt.RangingRequest, android.net.wifi.rtt.RangingResultCallback, android.os.Handler);
+ }
+
+}
+
package android.nfc {
public final class NfcAdapter {
@@ -4212,6 +4279,7 @@
method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
+ field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
}
public final class SubscriptionPlan implements android.os.Parcelable {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index f98d011..a3bf576 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -142,10 +142,7 @@
}
public class WifiManager {
- method public deprecated java.util.List<android.net.wifi.BatchedScanResult> getBatchedScanResults();
method public android.net.wifi.WifiConnectionStatistics getConnectionStatistics();
- method public deprecated boolean isBatchedScanSupported();
- method public deprecated boolean startLocationRestrictedScan(android.os.WorkSource);
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index cb4b1e4..b16e700 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -47,6 +47,7 @@
public class AppOpsManager {
method public static java.lang.String[] getOpStrs();
+ method public void setMode(int, int, java.lang.String, int);
field public static final java.lang.String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
field public static final java.lang.String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
field public static final java.lang.String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index b61cdec..e87a78e 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -23,8 +23,8 @@
import android.app.backup.IBackupObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
-import android.app.backup.RestoreSet;
import android.app.backup.ISelectBackupTransportCallback;
+import android.app.backup.RestoreSet;
import android.content.ComponentName;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
@@ -37,6 +37,7 @@
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -339,18 +340,16 @@
System.err.println(PM_NOT_RUNNING_ERR);
}
if (installedPackages != null) {
- List<String> packages = new ArrayList<>();
- for (PackageInfo pi : installedPackages) {
- try {
- if (mBmgr.isAppEligibleForBackup(pi.packageName)) {
- packages.add(pi.packageName);
- }
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(BMGR_NOT_RUNNING_ERR);
- }
+ String[] packages =
+ installedPackages.stream().map(p -> p.packageName).toArray(String[]::new);
+ String[] filteredPackages = {};
+ try {
+ filteredPackages = mBmgr.filterAppsEligibleForBackup(packages);
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
}
- backupNowPackages(packages, nonIncrementalBackup);
+ backupNowPackages(Arrays.asList(filteredPackages), nonIncrementalBackup);
}
}
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index e23e80a..847b26a 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -208,6 +208,19 @@
return true;
}
+std::string behead(std::string* line, const char cut) {
+ auto found = line->find_first_of(cut);
+ if (found == std::string::npos) {
+ std::string head = line->substr(0);
+ line->assign("");
+ return head;
+ }
+ std::string head = line->substr(0, found);
+ while(line->at(found) == cut) found++; // trim more cut of the rest
+ line->assign(line->substr(found));
+ return head;
+}
+
int toInt(const std::string& s) {
return atoi(s.c_str());
}
diff --git a/cmds/incident_helper/src/ih_util.h b/cmds/incident_helper/src/ih_util.h
index b063b2f..53f4438 100644
--- a/cmds/incident_helper/src/ih_util.h
+++ b/cmds/incident_helper/src/ih_util.h
@@ -34,6 +34,8 @@
const std::string DEFAULT_NEWLINE = "\r\n";
const std::string TAB_DELIMITER = "\t";
const std::string COMMA_DELIMITER = ",";
+const std::string PIPE_DELIMITER = "|";
+const std::string PARENTHESES_DELIMITER = "()";
// returns true if c is a-zA-Z0-9 or underscore
bool isValidChar(char c);
@@ -89,6 +91,11 @@
bool stripSuffix(std::string* line, const char* key, bool endAtDelimiter = false);
/**
+ * behead the given line by the cut, return the head and reassign the line to be the rest.
+ */
+std::string behead(std::string* line, const char cut);
+
+/**
* Converts string to the desired type
*/
int toInt(const std::string& s);
diff --git a/cmds/incident_helper/src/main.cpp b/cmds/incident_helper/src/main.cpp
index 8c6cd78..418dc3f 100644
--- a/cmds/incident_helper/src/main.cpp
+++ b/cmds/incident_helper/src/main.cpp
@@ -19,6 +19,7 @@
#include "parsers/BatteryTypeParser.h"
#include "parsers/CpuFreqParser.h"
#include "parsers/CpuInfoParser.h"
+#include "parsers/EventLogTagsParser.h"
#include "parsers/KernelWakesParser.h"
#include "parsers/PageTypeInfoParser.h"
#include "parsers/ProcrankParser.h"
@@ -55,6 +56,8 @@
// IDs larger than 1 are section ids reserved in incident.proto
case 1000:
return new SystemPropertiesParser();
+ case 1100:
+ return new EventLogTagsParser();
case 2000:
return new ProcrankParser();
case 2001:
diff --git a/cmds/incident_helper/src/parsers/EventLogTagsParser.cpp b/cmds/incident_helper/src/parsers/EventLogTagsParser.cpp
new file mode 100644
index 0000000..73e37bd
--- /dev/null
+++ b/cmds/incident_helper/src/parsers/EventLogTagsParser.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "incident_helper"
+
+#include <android/util/ProtoOutputStream.h>
+
+#include "frameworks/base/core/proto/android/util/event_log_tags.proto.h"
+#include "ih_util.h"
+#include "EventLogTagsParser.h"
+
+status_t
+EventLogTagsParser::Parse(const int in, const int out) const
+{
+ Reader reader(in);
+ string line;
+
+ ProtoOutputStream proto;
+
+ // parse line by line
+ while (reader.readLine(&line)) {
+ if (line.empty()) continue;
+ string debug = line;
+ string tagNumber = behead(&line, ' ');
+ string tagName = behead(&line, ' ');
+ if (tagNumber == "" || tagName == "") {
+ fprintf(stderr, "Bad line, expect at least two parts: %s[%s, %s]\n",
+ debug.c_str(), tagNumber.c_str(), tagName.c_str());
+ continue;
+ }
+
+ long long token = proto.start(EventLogTagMapProto::EVENT_LOG_TAGS);
+ proto.write(EventLogTag::TAG_NUMBER, toInt(tagNumber));
+ proto.write(EventLogTag::TAG_NAME, tagName);
+
+ record_t valueDescriptors = parseRecord(line, PARENTHESES_DELIMITER);
+ for (size_t i = 0; i < valueDescriptors.size(); i++) {
+ record_t valueDescriptor = parseRecord(valueDescriptors[i], PIPE_DELIMITER);
+ if (valueDescriptor.size() != 2 && valueDescriptor.size() != 3) {
+ // If the parts doesn't contains pipe, then skips it.
+ continue;
+ }
+ long long descriptorToken = proto.start(EventLogTag::VALUE_DESCRIPTORS);
+ proto.write(EventLogTag::ValueDescriptor::NAME, valueDescriptor[0]);
+ proto.write(EventLogTag::ValueDescriptor::TYPE, toInt(valueDescriptor[1]));
+ if (valueDescriptor.size() == 3) {
+ char c = valueDescriptor[2][0];
+ int unit = 0;
+ if (c < '0' || c > '9') {
+ unit = (int) c;
+ } else {
+ unit = toInt(valueDescriptor[2]);
+ }
+ proto.write(EventLogTag::ValueDescriptor::UNIT, unit);
+ }
+ proto.end(descriptorToken);
+ }
+ proto.end(token);
+ }
+
+ if (!reader.ok(&line)) {
+ fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str());
+ return -1;
+ }
+
+ if (!proto.flush(out)) {
+ fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
+ return -1;
+ }
+ fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size());
+ return NO_ERROR;
+}
diff --git a/cmds/incident_helper/src/parsers/EventLogTagsParser.h b/cmds/incident_helper/src/parsers/EventLogTagsParser.h
new file mode 100644
index 0000000..79057ce
--- /dev/null
+++ b/cmds/incident_helper/src/parsers/EventLogTagsParser.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EVENT_LOG_TAGS_PARSER_H
+#define EVENT_LOG_TAGS_PARSER_H
+
+#include "TextParserBase.h"
+
+using namespace android;
+
+/**
+ * event.logtags parser, parse file in /system/etc/event-log-tags
+ */
+class EventLogTagsParser : public TextParserBase {
+public:
+ EventLogTagsParser() : TextParserBase(String8("EventLogTagsParser")) {};
+ ~EventLogTagsParser() {};
+
+ virtual status_t Parse(const int in, const int out) const;
+};
+
+#endif // EVENT_LOG_TAGS_PARSER_H
diff --git a/cmds/incident_helper/testdata/event-log-tags.txt b/cmds/incident_helper/testdata/event-log-tags.txt
new file mode 100644
index 0000000..35396bf
--- /dev/null
+++ b/cmds/incident_helper/testdata/event-log-tags.txt
@@ -0,0 +1,6 @@
+42 answer (to life the universe etc|3)
+314 pi
+1004 chatty (dropped|3)
+1005 tag_def (tag|1),(name|3),(format|3)
+2747 contacts_aggregation (aggregation time|2|3), (count|1|1)
+1397638484 snet_event_log (subtag|3) (uid|1) (message|3|s)
\ No newline at end of file
diff --git a/cmds/incident_helper/tests/EventLogTagsParser_test.cpp b/cmds/incident_helper/tests/EventLogTagsParser_test.cpp
new file mode 100644
index 0000000..d0d1f1e
--- /dev/null
+++ b/cmds/incident_helper/tests/EventLogTagsParser_test.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EventLogTagsParser.h"
+
+#include "frameworks/base/core/proto/android/util/event_log_tags.pb.h"
+
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/message_lite.h>
+#include <gtest/gtest.h>
+#include <string.h>
+#include <fcntl.h>
+
+using namespace android::base;
+using namespace android::util;
+using namespace std;
+using ::testing::StrEq;
+using ::testing::Test;
+using ::testing::internal::CaptureStderr;
+using ::testing::internal::CaptureStdout;
+using ::testing::internal::GetCapturedStderr;
+using ::testing::internal::GetCapturedStdout;
+
+class EventLogTagsParserTest : public Test {
+public:
+ virtual void SetUp() override {
+ ASSERT_TRUE(tf.fd != -1);
+ }
+
+protected:
+ TemporaryFile tf;
+
+ const string kTestPath = GetExecutableDirectory();
+ const string kTestDataPath = kTestPath + "/testdata/";
+};
+
+TEST_F(EventLogTagsParserTest, Success) {
+ const string testFile = kTestDataPath + "event-log-tags.txt";
+
+ EventLogTagsParser parser;
+ EventLogTagMapProto expected;
+
+ EventLogTag* eventLogTag;
+ EventLogTag::ValueDescriptor* desp;
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(42);
+ eventLogTag->set_tag_name("answer");
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("to life the universe etc");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(314);
+ eventLogTag->set_tag_name("pi");
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(1004);
+ eventLogTag->set_tag_name("chatty");
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("dropped");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(1005);
+ eventLogTag->set_tag_name("tag_def");
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("tag");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_INT);
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("name");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("format");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(2747);
+ eventLogTag->set_tag_name("contacts_aggregation");
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("aggregation time");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_LONG);
+ desp->set_unit(EventLogTag_ValueDescriptor_DataUnit_MILLISECONDS);
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("count");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_INT);
+ desp->set_unit(EventLogTag_ValueDescriptor_DataUnit_OBJECTS);
+
+ eventLogTag = expected.add_event_log_tags();
+ eventLogTag->set_tag_number(1397638484);
+ eventLogTag->set_tag_name("snet_event_log");
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("subtag");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("uid");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_INT);
+ desp = eventLogTag->add_value_descriptors();
+ desp->set_name("message");
+ desp->set_type(EventLogTag_ValueDescriptor_DataType_STRING);
+ desp->set_unit(EventLogTag_ValueDescriptor_DataUnit_SECONDS);
+
+ int fd = open(testFile.c_str(), O_RDONLY);
+ ASSERT_TRUE(fd != -1);
+
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, parser.Parse(fd, STDOUT_FILENO));
+ EXPECT_EQ(GetCapturedStdout(), expected.SerializeAsString());
+ close(fd);
+}
diff --git a/cmds/incident_helper/tests/ih_util_test.cpp b/cmds/incident_helper/tests/ih_util_test.cpp
index 7b8cf52..efe714d 100644
--- a/cmds/incident_helper/tests/ih_util_test.cpp
+++ b/cmds/incident_helper/tests/ih_util_test.cpp
@@ -60,6 +60,9 @@
result = parseRecord("123,456,78_9", ",");
expected = { "123", "456", "78_9" };
EXPECT_EQ(expected, result);
+
+ result = parseRecord("", " ");
+ EXPECT_TRUE(result.empty());
}
TEST(IhUtilTest, ParseRecordByColumns) {
@@ -133,6 +136,22 @@
EXPECT_THAT(data4, StrEq(" 243%abc"));
}
+TEST(IhUtilTest, behead) {
+ string testcase1 = "81002 dropbox_file_copy (a)(b)";
+ EXPECT_THAT(behead(&testcase1, ' '), StrEq("81002"));
+ EXPECT_THAT(behead(&testcase1, ' '), StrEq("dropbox_file_copy"));
+ EXPECT_THAT(testcase1, "(a)(b)");
+
+ string testcase2 = "adbce,erwqr";
+ EXPECT_THAT(behead(&testcase2, ' '), StrEq("adbce,erwqr"));
+ EXPECT_THAT(testcase2, "");
+
+ string testcase3 = "first second";
+ EXPECT_THAT(behead(&testcase3, ' '), StrEq("first"));
+ EXPECT_THAT(behead(&testcase3, ' '), StrEq("second"));
+ EXPECT_THAT(testcase3, "");
+}
+
TEST(IhUtilTest, Reader) {
TemporaryFile tf;
ASSERT_NE(tf.fd, -1);
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 11d3e49..8420bc8 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -14,6 +14,9 @@
LOCAL_PATH:= $(call my-dir)
+# proto files used in incidentd to generate cppstream proto headers.
+PROTO_FILES:= frameworks/base/core/proto/android/util/log.proto
+
# ========= #
# incidentd #
# ========= #
@@ -59,20 +62,38 @@
libutils
LOCAL_MODULE_CLASS := EXECUTABLES
+
gen_src_dir := $(local-generated-sources-dir)
-GEN := $(gen_src_dir)/src/section_list.cpp
-$(GEN): $(HOST_OUT_EXECUTABLES)/incident-section-gen
-$(GEN): PRIVATE_CUSTOM_TOOL = \
+# generate section_list.cpp
+GEN_LIST := $(gen_src_dir)/src/section_list.cpp
+$(GEN_LIST): $(HOST_OUT_EXECUTABLES)/incident-section-gen
+$(GEN_LIST): PRIVATE_CUSTOM_TOOL = \
$(HOST_OUT_EXECUTABLES)/incident-section-gen incidentd > $@
-$(GEN): $(HOST_OUT_EXECUTABLES)/incident-section-gen
+$(GEN_LIST): $(HOST_OUT_EXECUTABLES)/incident-section-gen
$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
+LOCAL_GENERATED_SOURCES += $(GEN_LIST)
+GEN_LIST:=
+
+# generate cppstream proto, add proto files to PROTO_FILES
+GEN_PROTO := $(gen_src_dir)/proto.timestamp
+$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc $(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream $(PROTO_FILES)
+$(GEN_PROTO): PRIVATE_GEN_SRC_DIR := $(gen_src_dir)
+$(GEN_PROTO): PRIVATE_CUSTOM_TOOL = \
+ $(HOST_OUT_EXECUTABLES)/aprotoc --plugin=protoc-gen-cppstream=$(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream \
+ --cppstream_out=$(PRIVATE_GEN_SRC_DIR) -Iexternal/protobuf/src -I . \
+ $(PROTO_FILES) \
+ && touch $@
+$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN_PROTO)
+GEN_PROTO:=
gen_src_dir:=
-GEN:=
+ifeq ($(BUILD_WITH_INCIDENTD_RC), true)
LOCAL_INIT_RC := incidentd.rc
+endif
include $(BUILD_EXECUTABLE)
@@ -120,4 +141,22 @@
LOCAL_TEST_DATA := $(call find-test-data-in-subdirs, $(LOCAL_PATH), *, testdata)
+LOCAL_MODULE_CLASS := NATIVE_TESTS
+gen_src_dir := $(local-generated-sources-dir)
+# generate cppstream proto for testing
+GEN_PROTO := $(gen_src_dir)/log.proto.timestamp
+$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc $(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream $(PROTO_FILES)
+$(GEN_PROTO): PRIVATE_GEN_SRC_DIR := $(gen_src_dir)
+$(GEN_PROTO): PRIVATE_CUSTOM_TOOL = \
+ $(HOST_OUT_EXECUTABLES)/aprotoc --plugin=protoc-gen-cppstream=$(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream \
+ --cppstream_out=$(PRIVATE_GEN_SRC_DIR) -Iexternal/protobuf/src -I . \
+ $(PROTO_FILES) \
+ && touch $@
+$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN_PROTO)
+GEN_PROTO:=
+
+gen_src_dir:=
+
include $(BUILD_NATIVE_TEST)
diff --git a/cmds/incidentd/incidentd.rc b/cmds/incidentd/incidentd.rc
index fe38a71..66667dc 100644
--- a/cmds/incidentd/incidentd.rc
+++ b/cmds/incidentd/incidentd.rc
@@ -14,6 +14,8 @@
service incidentd /system/bin/incidentd
class main
+ user incidentd
+ group incidentd log
on post-fs-data
# Create directory for incidentd
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 22053ef..61d16f8 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -16,21 +16,29 @@
#define LOG_TAG "incidentd"
-#include "FdBuffer.h"
-#include "Privacy.h"
-#include "PrivacyBuffer.h"
#include "Section.h"
-#include "io_util.h"
-#include "section_list.h"
+#include <errno.h>
+#include <unistd.h>
+#include <wait.h>
+
+#include <memory>
+#include <mutex>
#include <android/util/protobuf.h>
-#include <private/android_filesystem_config.h>
#include <binder/IServiceManager.h>
-#include <map>
-#include <mutex>
-#include <wait.h>
-#include <unistd.h>
+#include <log/log_event_list.h>
+#include <log/logprint.h>
+#include <log/log_read.h>
+#include <private/android_filesystem_config.h> // for AID_NOBODY
+#include <private/android_logger.h>
+
+#include "FdBuffer.h"
+#include "frameworks/base/core/proto/android/util/log.proto.h"
+#include "io_util.h"
+#include "Privacy.h"
+#include "PrivacyBuffer.h"
+#include "section_list.h"
using namespace android::util;
using namespace std;
@@ -41,7 +49,7 @@
// incident section parameters
const int WAIT_MAX = 5;
const struct timespec WAIT_INTERVAL_NS = {0, 200 * 1000 * 1000};
-const char* INCIDENT_HELPER = "/system/bin/incident_helper";
+const char INCIDENT_HELPER[] = "/system/bin/incident_helper";
static pid_t
fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe)
@@ -609,3 +617,160 @@
return NO_ERROR;
}
+
+// ================================================================================
+// initialization only once in Section.cpp.
+map<log_id_t, log_time> LogSection::gLastLogsRetrieved;
+
+LogSection::LogSection(int id, log_id_t logID)
+ :WorkerThreadSection(id),
+ mLogID(logID)
+{
+ name += "logcat ";
+ name += android_log_id_to_name(logID);
+ switch (logID) {
+ case LOG_ID_EVENTS:
+ case LOG_ID_STATS:
+ case LOG_ID_SECURITY:
+ mBinary = true;
+ break;
+ default:
+ mBinary = false;
+ }
+}
+
+LogSection::~LogSection()
+{
+}
+
+static size_t
+trimTail(char const* buf, size_t len)
+{
+ while (len > 0) {
+ char c = buf[len - 1];
+ if (c == '\0' || c == ' ' || c == '\n' || c == '\r' || c == ':') {
+ len--;
+ } else {
+ break;
+ }
+ }
+ return len;
+}
+
+static inline int32_t get4LE(uint8_t const* src) {
+ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+}
+
+status_t
+LogSection::BlockingCall(int pipeWriteFd) const
+{
+ status_t err = NO_ERROR;
+ // Open log buffer and getting logs since last retrieved time if any.
+ unique_ptr<logger_list, void (*)(logger_list*)> loggers(
+ gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end() ?
+ android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0) :
+ android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+ gLastLogsRetrieved[mLogID], 0),
+ android_logger_list_free);
+
+ if (android_logger_open(loggers.get(), mLogID) == NULL) {
+ ALOGW("LogSection %s: Can't get logger.", this->name.string());
+ return err;
+ }
+
+ log_msg msg;
+ log_time lastTimestamp(0);
+
+ ProtoOutputStream proto;
+ while (true) { // keeps reading until logd buffer is fully read.
+ status_t err = android_logger_list_read(loggers.get(), &msg);
+ // err = 0 - no content, unexpected connection drop or EOF.
+ // err = +ive number - size of retrieved data from logger
+ // err = -ive number, OS supplied error _except_ for -EAGAIN
+ // err = -EAGAIN, graceful indication for ANDRODI_LOG_NONBLOCK that this is the end of data.
+ if (err <= 0) {
+ if (err != -EAGAIN) {
+ ALOGE("LogSection %s: fails to read a log_msg.\n", this->name.string());
+ }
+ break;
+ }
+ if (mBinary) {
+ // remove the first uint32 which is tag's index in event log tags
+ android_log_context context = create_android_log_parser(msg.msg() + sizeof(uint32_t),
+ msg.len() - sizeof(uint32_t));;
+ android_log_list_element elem;
+
+ lastTimestamp.tv_sec = msg.entry_v1.sec;
+ lastTimestamp.tv_nsec = msg.entry_v1.nsec;
+
+ // format a BinaryLogEntry
+ long long token = proto.start(LogProto::BINARY_LOGS);
+ proto.write(BinaryLogEntry::SEC, msg.entry_v1.sec);
+ proto.write(BinaryLogEntry::NANOSEC, msg.entry_v1.nsec);
+ proto.write(BinaryLogEntry::UID, (int) msg.entry_v4.uid);
+ proto.write(BinaryLogEntry::PID, msg.entry_v1.pid);
+ proto.write(BinaryLogEntry::TID, msg.entry_v1.tid);
+ proto.write(BinaryLogEntry::TAG_INDEX, get4LE(reinterpret_cast<uint8_t const*>(msg.msg())));
+ do {
+ elem = android_log_read_next(context);
+ long long elemToken = proto.start(BinaryLogEntry::ELEMS);
+ switch (elem.type) {
+ case EVENT_TYPE_INT:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_INT);
+ proto.write(BinaryLogEntry::Elem::VAL_INT32, (int) elem.data.int32);
+ break;
+ case EVENT_TYPE_LONG:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LONG);
+ proto.write(BinaryLogEntry::Elem::VAL_INT64, (long long) elem.data.int64);
+ break;
+ case EVENT_TYPE_STRING:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_STRING);
+ proto.write(BinaryLogEntry::Elem::VAL_STRING, elem.data.string, elem.len);
+ break;
+ case EVENT_TYPE_FLOAT:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_FLOAT);
+ proto.write(BinaryLogEntry::Elem::VAL_FLOAT, elem.data.float32);
+ break;
+ case EVENT_TYPE_LIST:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST);
+ break;
+ case EVENT_TYPE_LIST_STOP:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_LIST_STOP);
+ break;
+ case EVENT_TYPE_UNKNOWN:
+ proto.write(BinaryLogEntry::Elem::TYPE, BinaryLogEntry::Elem::EVENT_TYPE_UNKNOWN);
+ break;
+ }
+ proto.end(elemToken);
+ } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
+ proto.end(token);
+ if (context) {
+ android_log_destroy(&context);
+ }
+ } else {
+ AndroidLogEntry entry;
+ err = android_log_processLogBuffer(&msg.entry_v1, &entry);
+ if (err != NO_ERROR) {
+ ALOGE("LogSection %s: fails to process to an entry.\n", this->name.string());
+ break;
+ }
+ lastTimestamp.tv_sec = entry.tv_sec;
+ lastTimestamp.tv_nsec = entry.tv_nsec;
+
+ // format a TextLogEntry
+ long long token = proto.start(LogProto::TEXT_LOGS);
+ proto.write(TextLogEntry::SEC, (long long)entry.tv_sec);
+ proto.write(TextLogEntry::NANOSEC, (long long)entry.tv_nsec);
+ proto.write(TextLogEntry::PRIORITY, (int)entry.priority);
+ proto.write(TextLogEntry::UID, entry.uid);
+ proto.write(TextLogEntry::PID, entry.pid);
+ proto.write(TextLogEntry::TID, entry.tid);
+ proto.write(TextLogEntry::TAG, entry.tag, trimTail(entry.tag, entry.tagLen));
+ proto.write(TextLogEntry::LOG, entry.message, trimTail(entry.message, entry.messageLen));
+ proto.end(token);
+ }
+ }
+ gLastLogsRetrieved[mLogID] = lastTimestamp;
+ proto.flush(pipeWriteFd);
+ return err;
+}
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 64558a6..d440ee9 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -19,7 +19,9 @@
#include "Reporter.h"
+#include <map>
#include <stdarg.h>
+
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -122,5 +124,24 @@
Vector<String16> mArgs;
};
+/**
+ * Section that reads from logd.
+ */
+class LogSection : public WorkerThreadSection
+{
+ // global last log retrieved timestamp for each log_id_t.
+ static map<log_id_t, log_time> gLastLogsRetrieved;
+
+public:
+ LogSection(int id, log_id_t logID);
+ virtual ~LogSection();
+
+ virtual status_t BlockingCall(int pipeWriteFd) const;
+
+private:
+ log_id_t mLogID;
+ bool mBinary;
+};
+
#endif // SECTIONS_H
diff --git a/cmds/incidentd/src/section_list.h b/cmds/incidentd/src/section_list.h
index dfd2312..ddc0505 100644
--- a/cmds/incidentd/src/section_list.h
+++ b/cmds/incidentd/src/section_list.h
@@ -17,6 +17,8 @@
#ifndef SECTION_LIST_H
#define SECTION_LIST_H
+#include <log/log_event_list.h> // include log_id_t enums.
+
#include "Privacy.h"
#include "Section.h"
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 0c7876c..cbfb896 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -155,7 +155,7 @@
}
TEST(SectionTest, CommandSectionBadCommand) {
- CommandSection cs(NOOP_PARSER, "echo", "about", NULL);
+ CommandSection cs(NOOP_PARSER, "echoo", "about", NULL);
ReportRequestSet requests;
ASSERT_EQ(NAME_NOT_FOUND, cs.Execute(&requests));
}
@@ -167,6 +167,26 @@
ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
}
+TEST(SectionTest, LogSectionBinary) {
+ LogSection ls(1, LOG_ID_EVENTS);
+ ReportRequestSet requests;
+ requests.setMainFd(STDOUT_FILENO);
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
+ string results = GetCapturedStdout();
+ EXPECT_FALSE(results.empty());
+}
+
+TEST(SectionTest, LogSectionSystem) {
+ LogSection ls(1, LOG_ID_SYSTEM);
+ ReportRequestSet requests;
+ requests.setMainFd(STDOUT_FILENO);
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
+ string results = GetCapturedStdout();
+ EXPECT_FALSE(results.empty());
+}
+
TEST(SectionTest, TestFilterPiiTaggedFields) {
TemporaryFile tf;
FileSection fs(NOOP_PARSER, tf.path);
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index d829243..ffe652f 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -34,6 +34,7 @@
src/config/ConfigKey.cpp \
src/config/ConfigListener.cpp \
src/config/ConfigManager.cpp \
+ src/external/StatsPuller.cpp \
src/external/StatsCompanionServicePuller.cpp \
src/external/ResourcePowerManagerPuller.cpp \
src/external/CpuTimePerUidPuller.cpp \
@@ -184,7 +185,8 @@
tests/metrics/metrics_test_helper.cpp \
tests/statsd_test_util.cpp \
tests/e2e/WakelockDuration_e2e_test.cpp \
- tests/e2e/MetricConditionLink_e2e_test.cpp
+ tests/e2e/MetricConditionLink_e2e_test.cpp \
+ tests/e2e/Attribution_e2e_test.cpp
LOCAL_STATIC_LIBRARIES := \
$(statsd_common_static_libraries) \
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 991badc..1cfec32 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -25,6 +25,8 @@
#include "guardrail/StatsdStats.h"
#include "metrics/CountMetricProducer.h"
#include "external/StatsPullerManager.h"
+#include "dimension.h"
+#include "field_util.h"
#include "stats_util.h"
#include "storage/StorageManager.h"
@@ -82,40 +84,67 @@
void StatsLogProcessor::onAnomalyAlarmFired(
const uint64_t timestampNs,
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet) {
- // TODO: This is a thread-safety issue. mMetricsManagers could change under our feet.
- // TODO: Solution? Lock everything! :(
- // TODO: Question: Can we replace the other lock (broadcast), or do we need to supplement it?
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
for (const auto& itr : mMetricsManagers) {
itr.second->onAnomalyAlarmFired(timestampNs, anomalySet);
}
}
-// TODO: what if statsd service restarts? How do we know what logs are already processed before?
-void StatsLogProcessor::OnLogEvent(const LogEvent& msg) {
- StatsdStats::getInstance().noteAtomLogged(msg.GetTagId(), msg.GetTimestampNs() / NS_PER_SEC);
- // pass the event to metrics managers.
- for (auto& pair : mMetricsManagers) {
- pair.second->onLogEvent(msg);
- flushIfNecessary(msg.GetTimestampNs(), pair.first, *(pair.second));
- }
- // Hard-coded logic to update the isolated uid's in the uid-map.
- // The field numbers need to be currently updated by hand with atoms.proto
- if (msg.GetTagId() == android::util::ISOLATED_UID_CHANGED) {
- status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR;
- bool is_create = msg.GetBool(3, &err);
- auto parent_uid = int(msg.GetLong(1, &err2));
- auto isolated_uid = int(msg.GetLong(2, &err3));
- if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) {
- if (is_create) {
- mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
- } else {
- mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
- }
+void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
+ std::vector<Field> uidFields;
+ findFields(
+ event->getFieldValueMap(),
+ buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY),
+ &uidFields);
+ for (size_t i = 0; i < uidFields.size(); ++i) {
+ DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]);
+ if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) {
+ const int uid = mUidMap->getHostUidOrSelf(value->value_int());
+ value->set_value_int(uid);
}
}
}
+void StatsLogProcessor::onIsolatedUidChangedEventLocked(const LogEvent& event) {
+ status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR;
+ bool is_create = event.GetBool(3, &err);
+ auto parent_uid = int(event.GetLong(1, &err2));
+ auto isolated_uid = int(event.GetLong(2, &err3));
+ if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) {
+ if (is_create) {
+ mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
+ } else {
+ mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
+ }
+ } else {
+ ALOGE("Failed to parse uid in the isolated uid change event.");
+ }
+}
+
+// TODO: what if statsd service restarts? How do we know what logs are already processed before?
+void StatsLogProcessor::OnLogEvent(LogEvent* event) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
+ StatsdStats::getInstance().noteAtomLogged(
+ event->GetTagId(), event->GetTimestampNs() / NS_PER_SEC);
+
+ // Hard-coded logic to update the isolated uid's in the uid-map.
+ // The field numbers need to be currently updated by hand with atoms.proto
+ if (event->GetTagId() == android::util::ISOLATED_UID_CHANGED) {
+ onIsolatedUidChangedEventLocked(*event);
+ } else {
+ // Map the isolated uid to host uid if necessary.
+ mapIsolatedUidToHostUidIfNecessaryLocked(event);
+ }
+
+ // pass the event to metrics managers.
+ for (auto& pair : mMetricsManagers) {
+ pair.second->onLogEvent(*event);
+ flushIfNecessaryLocked(event->GetTimestampNs(), pair.first, *(pair.second));
+ }
+}
+
void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
ALOGD("Updated configuration for key %s", key.ToString().c_str());
sp<MetricsManager> newMetricsManager = new MetricsManager(key, config, mTimeBaseSec, mUidMap);
auto it = mMetricsManagers.find(key);
@@ -142,6 +171,7 @@
}
size_t StatsLogProcessor::GetMetricsSize(const ConfigKey& key) const {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it == mMetricsManagers.end()) {
ALOGW("Config source %s does not exist", key.ToString().c_str());
@@ -152,6 +182,7 @@
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
ConfigMetricsReportList* report) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it == mMetricsManagers.end()) {
ALOGW("Config source %s does not exist", key.ToString().c_str());
@@ -165,6 +196,7 @@
}
void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outData) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it == mMetricsManagers.end()) {
ALOGW("Config source %s does not exist", key.ToString().c_str());
@@ -173,9 +205,7 @@
// This allows another broadcast to be sent within the rate-limit period if we get close to
// filling the buffer again soon.
- mBroadcastTimesMutex.lock();
mLastBroadcastTimes.erase(key);
- mBroadcastTimesMutex.unlock();
ProtoOutputStream proto;
@@ -224,6 +254,7 @@
}
void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
mMetricsManagers.erase(it);
@@ -231,14 +262,11 @@
}
StatsdStats::getInstance().noteConfigRemoved(key);
- std::lock_guard<std::mutex> lock(mBroadcastTimesMutex);
mLastBroadcastTimes.erase(key);
}
-void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs, const ConfigKey& key,
- MetricsManager& metricsManager) {
- std::lock_guard<std::mutex> lock(mBroadcastTimesMutex);
-
+void StatsLogProcessor::flushIfNecessaryLocked(
+ uint64_t timestampNs, const ConfigKey& key, MetricsManager& metricsManager) {
auto lastCheckTime = mLastByteSizeTimes.find(key);
if (lastCheckTime != mLastByteSizeTimes.end()) {
if (timestampNs - lastCheckTime->second < StatsdStats::kMinByteSizeCheckPeriodNs) {
@@ -274,6 +302,7 @@
void StatsLogProcessor::WriteDataToDisk() {
mkdir(STATS_DATA_DIR, S_IRWXU);
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
for (auto& pair : mMetricsManagers) {
const ConfigKey& key = pair.first;
vector<uint8_t> data;
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index f62fc4e..09e10a1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -38,7 +38,7 @@
const std::function<void(const ConfigKey&)>& sendBroadcast);
virtual ~StatsLogProcessor();
- void OnLogEvent(const LogEvent& event);
+ void OnLogEvent(LogEvent* event);
void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config);
void OnConfigRemoved(const ConfigKey& key);
@@ -46,7 +46,8 @@
size_t GetMetricsSize(const ConfigKey& key) const;
void onDumpReport(const ConfigKey& key, vector<uint8_t>* outData);
- void onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs, ConfigMetricsReportList* report);
+ void onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
+ ConfigMetricsReportList* report);
/* Tells MetricsManager that the alarms in anomalySet have fired. Modifies anomalySet. */
void onAnomalyAlarmFired(
@@ -56,8 +57,12 @@
/* Flushes data to disk. Data on memory will be gone after written to disk. */
void WriteDataToDisk();
+ inline sp<UidMap> getUidMap() {
+ return mUidMap;
+ }
+
private:
- mutable mutex mBroadcastTimesMutex;
+ mutable mutex mMetricsMutex;
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
@@ -72,8 +77,14 @@
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
* actually delete the data. */
- void flushIfNecessary(uint64_t timestampNs, const ConfigKey& key,
- MetricsManager& metricsManager);
+ void flushIfNecessaryLocked(uint64_t timestampNs, const ConfigKey& key,
+ MetricsManager& metricsManager);
+
+ // Maps the isolated uid in the log event to host uid if the log event contains uid fields.
+ void mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const;
+
+ // Handler over the isolated uid change event.
+ void onIsolatedUidChangedEventLocked(const LogEvent& event);
// Function used to send a broadcast so that receiver for the config key can call getData
// to retrieve the stored data.
@@ -87,6 +98,7 @@
FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
+ FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
};
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 45f1ea1..0ed1c1f 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -695,7 +695,7 @@
mConfigManager->Startup();
}
-void StatsService::OnLogEvent(const LogEvent& event) {
+void StatsService::OnLogEvent(LogEvent* event) {
mProcessor->OnLogEvent(event);
}
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index c0424f3..8d29970 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -72,7 +72,7 @@
/**
* Called by LogReader when there's a log event to process.
*/
- virtual void OnLogEvent(const LogEvent& event);
+ virtual void OnLogEvent(LogEvent* event);
/**
* Binder call for clients to request data for this configuration key.
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 05c68e1..f10b2cf 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -162,45 +162,23 @@
return 0;
}
-bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum,
- const DimToValMap& currentBucket) {
- if (currentBucketNum > mMostRecentBucketNum + 1) {
- addPastBucket(nullptr, currentBucketNum - 1);
- }
- for (auto itr = currentBucket.begin(); itr != currentBucket.end(); itr++) {
- if (itr->second + getSumOverPastBuckets(itr->first) > mAlert.trigger_if_sum_gt()) {
- return true;
- }
- }
- // In theory, we also need to check the dimsions not in the current bucket. In single-thread
- // mode, usually we could avoid the following loops.
- for (auto itr = mSumOverPastBuckets.begin(); itr != mSumOverPastBuckets.end(); itr++) {
- if (itr->second > mAlert.trigger_if_sum_gt()) {
- return true;
- }
- }
- return false;
-}
-
bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const HashableDimensionKey& key,
const int64_t& currentBucketValue) {
if (currentBucketNum > mMostRecentBucketNum + 1) {
+ // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this.
addPastBucket(key, 0, currentBucketNum - 1);
}
return mAlert.has_trigger_if_sum_gt()
&& getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
}
-void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs) {
- // TODO: This should also take in the const HashableDimensionKey& key, to pass
- // more details to incidentd and to make mRefractoryPeriodEndsSec key-specific.
+void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const HashableDimensionKey& key) {
// TODO: Why receive timestamp? RefractoryPeriod should always be based on real time right now.
- if (isInRefractoryPeriod(timestampNs)) {
+ if (isInRefractoryPeriod(timestampNs, key)) {
VLOG("Skipping anomaly declaration since within refractory period");
return;
}
- // TODO(guardrail): Consider guarding against too short refractory periods.
- mLastAnomalyTimestampNs = timestampNs;
+ mRefractoryPeriodEndsSec[key] = (timestampNs / NS_PER_SEC) + mAlert.refractory_period_secs();
// TODO: If we had access to the bucket_size_millis, consider calling resetStorage()
// if (mAlert.refractory_period_secs() > mNumOfPastBuckets * bucketSizeNs) { resetStorage(); }
@@ -208,7 +186,7 @@
if (!mSubscriptions.empty()) {
if (mAlert.has_id()) {
ALOGI("An anomaly (%llu) has occurred! Informing subscribers.",mAlert.id());
- informSubscribers();
+ informSubscribers(key);
} else {
ALOGI("An anomaly (with no id) has occurred! Not informing any subscribers.");
}
@@ -218,6 +196,7 @@
StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.id());
+ // TODO: This should also take in the const HashableDimensionKey& key?
android::util::stats_write(android::util::ANOMALY_DETECTED, mConfigKey.GetUid(),
mConfigKey.GetId(), mAlert.id());
}
@@ -227,24 +206,24 @@
const HashableDimensionKey& key,
const int64_t& currentBucketValue) {
if (detectAnomaly(currBucketNum, key, currentBucketValue)) {
- declareAnomaly(timestampNs);
+ declareAnomaly(timestampNs, key);
}
}
-void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs,
- const int64_t& currBucketNum,
- const DimToValMap& currentBucket) {
- if (detectAnomaly(currBucketNum, currentBucket)) {
- declareAnomaly(timestampNs);
+bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs,
+ const HashableDimensionKey& key) {
+ const auto& it = mRefractoryPeriodEndsSec.find(key);
+ if (it != mRefractoryPeriodEndsSec.end()) {
+ if ((timestampNs / NS_PER_SEC) <= it->second) {
+ return true;
+ } else {
+ mRefractoryPeriodEndsSec.erase(key);
+ }
}
+ return false;
}
-bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs) const {
- return mLastAnomalyTimestampNs >= 0 &&
- timestampNs - mLastAnomalyTimestampNs <= mAlert.refractory_period_secs() * NS_PER_SEC;
-}
-
-void AnomalyTracker::informSubscribers() {
+void AnomalyTracker::informSubscribers(const HashableDimensionKey& key) {
VLOG("informSubscribers called.");
if (mSubscriptions.empty()) {
ALOGE("Attempt to call with no subscribers.");
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 2d5ab86..472c02c 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -52,17 +52,14 @@
const int64_t& bucketNum);
// Returns true if detected anomaly for the existing buckets on one or more dimension keys.
- bool detectAnomaly(const int64_t& currBucketNum, const DimToValMap& currentBucket);
bool detectAnomaly(const int64_t& currBucketNum, const HashableDimensionKey& key,
const int64_t& currentBucketValue);
// Informs incidentd about the detected alert.
- void declareAnomaly(const uint64_t& timestampNs);
+ void declareAnomaly(const uint64_t& timestampNs, const HashableDimensionKey& key);
// Detects the alert and informs the incidentd when applicable.
void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum,
- const DimToValMap& currentBucket);
- void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum,
const HashableDimensionKey& key,
const int64_t& currentBucketValue);
@@ -82,9 +79,11 @@
return mAlert.trigger_if_sum_gt();
}
- // Helper function to return the timestamp of the last detected anomaly.
- inline int64_t getLastAnomalyTimestampNs() const {
- return mLastAnomalyTimestampNs;
+ // Returns the refractory period timestamp (in seconds) for the given key.
+ // If there is no stored refractory period ending timestamp, returns 0.
+ uint32_t getRefractoryPeriodEndsSec(const HashableDimensionKey& key) const {
+ const auto& it = mRefractoryPeriodEndsSec.find(key);
+ return it != mRefractoryPeriodEndsSec.end() ? it->second : 0;
}
inline int getNumOfPastBuckets() const {
@@ -121,8 +120,11 @@
// The bucket number of the last added bucket.
int64_t mMostRecentBucketNum = -1;
- // The timestamp when the last anomaly was declared.
- int64_t mLastAnomalyTimestampNs = -1;
+ // Map from each dimension to the timestamp that its refractory period (if this anomaly was
+ // declared for that dimension) ends, in seconds. Only anomalies that occur after this period
+ // ends will be declared.
+ // Entries may be, but are not guaranteed to be, removed after the period is finished.
+ unordered_map<HashableDimensionKey, uint32_t> mRefractoryPeriodEndsSec;
void flushPastBuckets(const int64_t& currBucketNum);
@@ -133,7 +135,7 @@
// and remove any items with value 0.
void subtractBucketFromSum(const shared_ptr<DimToValMap>& bucket);
- bool isInRefractoryPeriod(const uint64_t& timestampNs) const;
+ bool isInRefractoryPeriod(const uint64_t& timestampNs, const HashableDimensionKey& key);
// Calculates the corresponding bucket index within the circular array.
size_t index(int64_t bucketNum) const;
@@ -142,12 +144,12 @@
virtual void resetStorage();
// Informs the subscribers that an anomaly has occurred.
- void informSubscribers();
+ void informSubscribers(const HashableDimensionKey& key);
FRIEND_TEST(AnomalyTrackerTest, TestConsecutiveBuckets);
FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets);
FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection);
- FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetection);
+ FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced);
};
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index d30810f..7576a38 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -46,7 +46,7 @@
if (itr->second != nullptr &&
static_cast<uint32_t>(timestampNs / NS_PER_SEC) >= itr->second->timestampSec) {
- declareAnomaly(timestampNs);
+ declareAnomaly(timestampNs, dimensionKey);
stopAlarm(dimensionKey);
}
}
@@ -55,7 +55,7 @@
const uint64_t& timestampNs) {
uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC);
- if (isInRefractoryPeriod(timestampNs)) {
+ if (isInRefractoryPeriod(timestampNs, dimensionKey)) {
VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period");
return;
}
@@ -104,7 +104,7 @@
// Now declare each of these alarms to have fired.
for (const auto& kv : matchedAlarms) {
- declareAnomaly(timestampNs /* TODO: , kv.first */);
+ declareAnomaly(timestampNs, kv.first);
mAlarms.erase(kv.first);
firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
}
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
index 182ce3b..de7093d 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -50,7 +50,7 @@
const uint64_t& timestampNs);
// Declares an anomaly for each alarm in firedAlarms that belongs to this DurationAnomalyTracker
- // and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor.
+ // and removes it from firedAlarms.
// TODO: This will actually be called from a different thread, so make it thread-safe!
// This means that almost every function in DurationAnomalyTracker needs to be locked.
// But this should be done at the level of StatsLogProcessor, which needs to lock
@@ -70,10 +70,10 @@
void resetStorage() override;
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
};
} // namespace statsd
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 221a554..7f77ef7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -81,25 +81,28 @@
DropboxErrorChanged dropbox_error_changed = 45;
AnomalyDetected anomaly_detected = 46;
AppHook app_hook = 47;
+ AppStartChanged app_start_changed = 48;
+ AppStartCancelChanged app_start_cancel_changed = 49;
+ AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
// TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
}
- // Pulled events will start at field 1000.
+ // Pulled events will start at field 10000.
oneof pulled {
- WifiBytesTransfer wifi_bytes_transfer = 1000;
- WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 1001;
- MobileBytesTransfer mobile_bytes_transfer = 1002;
- MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 1003;
- KernelWakelock kernel_wakelock = 1004;
- PlatformSleepState platform_sleep_state = 1005;
- SleepStateVoter sleep_state_voter = 1006;
- SubsystemSleepState subsystem_sleep_state = 1007;
- CpuTimePerFreq cpu_time_per_freq = 1008;
- CpuTimePerUid cpu_time_per_uid = 1009;
- CpuTimePerUidFreq cpu_time_per_uid_freq = 1010;
- WifiActivityEnergyInfo wifi_activity_energy_info = 1011;
- ModemActivityInfo modem_activity_info = 1012;
- AttributionChainDummyAtom attribution_chain_dummy_atom = 10000;
+ WifiBytesTransfer wifi_bytes_transfer = 10000;
+ WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
+ MobileBytesTransfer mobile_bytes_transfer = 10002;
+ MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003;
+ KernelWakelock kernel_wakelock = 10004;
+ PlatformSleepState platform_sleep_state = 10005;
+ SleepStateVoter sleep_state_voter = 10006;
+ SubsystemSleepState subsystem_sleep_state = 10007;
+ CpuTimePerFreq cpu_time_per_freq = 10008;
+ CpuTimePerUid cpu_time_per_uid = 10009;
+ CpuTimePerUidFreq cpu_time_per_uid_freq = 10010;
+ WifiActivityEnergyInfo wifi_activity_energy_info = 10011;
+ ModemActivityInfo modem_activity_info = 10012;
+ AttributionChainDummyAtom attribution_chain_dummy_atom = 100000;
}
}
@@ -800,16 +803,19 @@
optional string process_name = 3;
// The pid if available. -1 means not available.
- optional int32 pid = 4;
+ optional sint32 pid = 4;
// 1 indicates is instant app. -1 indicates Not applicable.
- optional int32 is_instant_app = 5;
+ optional sint32 is_instant_app = 5;
// The activity name if available.
optional string activity_name = 6;
+ // The package name if available.
+ optional string package_name = 7;
+
// 1 indicates in foreground. -1 indicates not available.
- optional int32 is_foreground = 7;
+ optional sint32 is_foreground = 8;
}
/*
@@ -852,6 +858,100 @@
optional int64 alert_id = 3;
}
+message AppStartChanged {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1;
+
+ // The app package name.
+ optional string pkg_name = 2;
+
+ enum TransitionType {
+ APP_START_TRANSITION_TYPE_UNKNOWN = 0;
+ WARM = 1;
+ HOT = 2;
+ COLD = 3;
+ }
+ // The transition type.
+ optional TransitionType type = 3;
+
+ // The activity name.
+ optional string activity_name = 4;
+
+ // The name of the calling app. Empty if not set.
+ optional string calling_pkg_name = 5;
+
+ // Whether the app is an instant app.
+ optional bool is_instant_app = 6;
+
+ // Device uptime when activity started.
+ optional int64 activity_start_msec = 7;
+
+ // TODO: Update android/app/ActivityManagerInternal.java constants to depend on our proto enum.
+ enum TransitionReason {
+ APP_START_TRANSITION_REASON_UNKNOWN = 0;
+ SPLASH_SCREEN = 1;
+ WINDOWS_DRAWN = 2;
+ TIMEOUT = 3;
+ SNAPSHOT = 4;
+ }
+ optional TransitionReason reason = 8;
+
+ optional int32 transition_delay_msec = 9;
+ // -1 if not set.
+ optional int32 starting_window_delay_msec = 10;
+ // -1 if not set.
+ optional int32 bind_application_delay_msec = 11;
+ optional int32 windows_drawn_delay_msec = 12;
+
+ // Empty if not set.
+ optional string launch_token = 13;
+
+}
+
+message AppStartCancelChanged {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1;
+
+ // The app package name.
+ optional string pkg_name = 2;
+
+ enum TransitionType {
+ APP_START_TRANSITION_TYPE_UNKNOWN = 0;
+ WARM = 1;
+ HOT = 2;
+ COLD = 3;
+ }
+ // The transition type.
+ optional TransitionType type = 3;
+
+ // The activity name.
+ optional string activity_name = 4;
+}
+
+message AppStartFullyDrawnChanged {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1;
+
+ // The app package name.
+ optional string pkg_name = 2;
+
+ enum TransitionType {
+ APP_START_TRANSITION_TYPE_UNKNOWN = 0;
+ WITH_BUNDLE = 1;
+ WITHOUT_BUNDLE = 2;
+ }
+ // The transition type.
+ optional TransitionType type = 3;
+
+ // The activity name.
+ optional string activity_name = 4;
+
+ optional bool transition_process_running = 5;
+
+ // App startup time (until call to Activity#reportFullyDrawn()).
+ optional int64 app_startup_time_ms = 6;
+}
+
/**
* Pulls bytes transferred via wifi (Sum of foreground and background usage).
*
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
index 45b3586..09499b6 100644
--- a/cmds/statsd/src/dimension.cpp
+++ b/cmds/statsd/src/dimension.cpp
@@ -19,7 +19,6 @@
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
#include "dimension.h"
-#include "field_util.h"
namespace android {
@@ -220,33 +219,35 @@
constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1;
constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2;
-void buildAttributionUidFieldMatcher(const int tagId, const Position position,
- FieldMatcher *matcher) {
- matcher->set_field(tagId);
- matcher->add_child()->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
- FieldMatcher* child = matcher->mutable_child(0)->add_child();
- child->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-}
-
-void buildAttributionTagFieldMatcher(const int tagId, const Position position,
- FieldMatcher *matcher) {
- matcher->set_field(tagId);
- FieldMatcher* child = matcher->add_child();
+FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) {
+ FieldMatcher matcher;
+ matcher.set_field(tagId);
+ auto child = matcher.add_child();
child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
child->set_position(position);
- child = child->add_child();
- child->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ return matcher;
}
-void buildAttributionFieldMatcher(const int tagId, const Position position,
- FieldMatcher *matcher) {
- matcher->set_field(tagId);
- FieldMatcher* child = matcher->add_child();
+FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) {
+ FieldMatcher matcher;
+ matcher.set_field(tagId);
+ FieldMatcher* child = matcher.add_child();
child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
child->set_position(position);
- child = child->add_child();
- child->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
- child->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ return matcher;
+}
+
+FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) {
+ FieldMatcher matcher;
+ matcher.set_field(tagId);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
+ child->set_position(position);
+ child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+ return matcher;
}
void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) {
diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h
index 5bb64a9..845c138 100644
--- a/cmds/statsd/src/dimension.h
+++ b/cmds/statsd/src/dimension.h
@@ -27,7 +27,6 @@
namespace os {
namespace statsd {
-
// Returns the leaf node from the DimensionsValue proto. It assume that the input has only one
// leaf node at most.
const DimensionsValue* getSingleLeafValue(const DimensionsValue* value);
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
index 9738760..a61afb4 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
@@ -20,6 +20,9 @@
#include <fstream>
#include "external/CpuTimePerUidFreqPuller.h"
+#include "../guardrail/StatsdStats.h"
+#include "CpuTimePerUidFreqPuller.h"
+#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "statslog.h"
@@ -45,43 +48,47 @@
* This provides the times a UID's processes spent executing at each different cpu frequency.
* The file contains a monotonically increasing count of time for a single boot.
*/
-bool CpuTimePerUidFreqPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
- data->clear();
+CpuTimePerUidFreqPuller::CpuTimePerUidFreqPuller()
+ : StatsPuller(android::util::CPU_TIME_PER_UID_FREQ) {
+}
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
+bool CpuTimePerUidFreqPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ data->clear();
- uint64_t timestamp = time(nullptr) * NS_PER_SEC;
- char buf[kLineBufferSize];
- // first line prints the format and frequencies
- fin.getline(buf, kLineBufferSize);
- char * pch;
- while(!fin.eof()){
+ ifstream fin;
+ fin.open(sProcFile);
+ if (!fin.good()) {
+ VLOG("Failed to read pseudo file %s", sProcFile.c_str());
+ return false;
+ }
+
+ uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+ char buf[kLineBufferSize];
+ // first line prints the format and frequencies
fin.getline(buf, kLineBufferSize);
- pch = strtok (buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(NULL, " ");
- uint64_t timeMs;
- int idx = 0;
- do {
- timeMs = std::stoull(pch);
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp);
- ptr->write(uid);
- ptr->write(idx);
- ptr->write(timeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
- idx ++;
- pch = strtok(NULL, " ");
- } while (pch != NULL);
- }
- return true;
+ char* pch;
+ while (!fin.eof()) {
+ fin.getline(buf, kLineBufferSize);
+ pch = strtok(buf, " :");
+ if (pch == NULL) break;
+ uint64_t uid = std::stoull(pch);
+ pch = strtok(NULL, " ");
+ uint64_t timeMs;
+ int idx = 0;
+ do {
+ timeMs = std::stoull(pch);
+ auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp);
+ ptr->write(uid);
+ ptr->write(idx);
+ ptr->write(timeMs);
+ ptr->init();
+ data->push_back(ptr);
+ VLOG("uid %lld, freq idx %d, sys time %lld", (long long)uid, idx, (long long)timeMs);
+ idx++;
+ pch = strtok(NULL, " ");
+ } while (pch != NULL);
+ }
+ return true;
}
} // namespace statsd
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h
index 839e5aa..6f6c669 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.h
@@ -33,7 +33,8 @@
*/
class CpuTimePerUidFreqPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ CpuTimePerUidFreqPuller();
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
index f69b9b5..e7ea4b9 100644
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp
@@ -20,6 +20,8 @@
#include <fstream>
#include "external/CpuTimePerUidPuller.h"
+#include "CpuTimePerUidPuller.h"
+#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "statslog.h"
@@ -42,38 +44,42 @@
* This provides the time a UID's processes spent executing in user-space and kernel-space.
* The file contains a monotonically increasing count of time for a single boot.
*/
-bool CpuTimePerUidPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
- data->clear();
+CpuTimePerUidPuller::CpuTimePerUidPuller() : StatsPuller(android::util::CPU_TIME_PER_UID) {
+}
- ifstream fin;
- fin.open(sProcFile);
- if (!fin.good()) {
- VLOG("Failed to read pseudo file %s", sProcFile.c_str());
- return false;
- }
+bool CpuTimePerUidPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ data->clear();
- uint64_t timestamp = time(nullptr) * NS_PER_SEC;
- char buf[kLineBufferSize];
- char * pch;
- while(!fin.eof()){
- fin.getline(buf, kLineBufferSize);
- pch = strtok(buf, " :");
- if (pch == NULL) break;
- uint64_t uid = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t userTimeMs = std::stoull(pch);
- pch = strtok(buf, " ");
- uint64_t sysTimeMs = std::stoull(pch);
+ ifstream fin;
+ fin.open(sProcFile);
+ if (!fin.good()) {
+ VLOG("Failed to read pseudo file %s", sProcFile.c_str());
+ return false;
+ }
- auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp);
- ptr->write(uid);
- ptr->write(userTimeMs);
- ptr->write(sysTimeMs);
- ptr->init();
- data->push_back(ptr);
- VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs, (long long)sysTimeMs);
- }
- return true;
+ uint64_t timestamp = time(nullptr) * NS_PER_SEC;
+ char buf[kLineBufferSize];
+ char* pch;
+ while (!fin.eof()) {
+ fin.getline(buf, kLineBufferSize);
+ pch = strtok(buf, " :");
+ if (pch == NULL) break;
+ uint64_t uid = std::stoull(pch);
+ pch = strtok(buf, " ");
+ uint64_t userTimeMs = std::stoull(pch);
+ pch = strtok(buf, " ");
+ uint64_t sysTimeMs = std::stoull(pch);
+
+ auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp);
+ ptr->write(uid);
+ ptr->write(userTimeMs);
+ ptr->write(sysTimeMs);
+ ptr->init();
+ data->push_back(ptr);
+ VLOG("uid %lld, user time %lld, sys time %lld", (long long)uid, (long long)userTimeMs,
+ (long long)sysTimeMs);
+ }
+ return true;
}
} // namespace statsd
diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.h b/cmds/statsd/src/external/CpuTimePerUidPuller.h
index 9bb8946..d0d39d0 100644
--- a/cmds/statsd/src/external/CpuTimePerUidPuller.h
+++ b/cmds/statsd/src/external/CpuTimePerUidPuller.h
@@ -33,7 +33,8 @@
*/
class CpuTimePerUidPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ CpuTimePerUidPuller();
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp b/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
index cb9f1cc..2e29fb0 100644
--- a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
@@ -33,6 +33,7 @@
#include "external/ResourcePowerManagerPuller.h"
#include "external/StatsPuller.h"
+#include "ResourcePowerManagerPuller.h"
#include "logd/LogEvent.h"
#include "statslog.h"
@@ -72,7 +73,10 @@
return gPowerHalV1_0 != nullptr;
}
-bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
+ResourcePowerManagerPuller::ResourcePowerManagerPuller(int tagId) : StatsPuller(tagId) {
+}
+
+bool ResourcePowerManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (!getPowerHal()) {
@@ -83,79 +87,87 @@
uint64_t timestamp = time(nullptr) * NS_PER_SEC;
data->clear();
- Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
- [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
- if (status != Status::SUCCESS) return;
-
- for (size_t i = 0; i < states.size(); i++) {
- const PowerStatePlatformSleepState& state = states[i];
-
- auto statePtr = make_shared<LogEvent>(
- android::util::PLATFORM_SLEEP_STATE, timestamp);
- statePtr->write(state.name);
- statePtr->write(state.residencyInMsecSinceBoot);
- statePtr->write(state.totalTransitions);
- statePtr->write(state.supportedOnlyInSuspend);
- statePtr->init();
- data->push_back(statePtr);
- VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0);
- for (auto voter : state.voters) {
- auto voterPtr =
- make_shared<LogEvent>(android::util::SLEEP_STATE_VOTER, timestamp);
- voterPtr->write(state.name);
- voterPtr->write(voter.name);
- voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
- voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
- voterPtr->init();
- data->push_back(voterPtr);
- VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
- voter.name.c_str(), (long long)voter.totalTimeInMsecVotedForSinceBoot,
- (long long)voter.totalNumberOfTimesVotedSinceBoot);
- }
- }
- });
- if (!ret.isOk()) {
- ALOGE("getLowPowerStats() failed: power HAL service not available");
- gPowerHalV1_0 = nullptr;
- return false;
- }
-
- // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
- sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
- android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
- if (gPowerHal_1_1 != nullptr) {
- ret = gPowerHal_1_1->getSubsystemLowPowerStats(
- [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
-
+ Return<void> ret;
+ if (mTagId == android::util::PLATFORM_SLEEP_STATE ||
+ mTagId == android::util::SLEEP_STATE_VOTER) {
+ ret = gPowerHalV1_0->getPlatformLowPowerStats(
+ [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
if (status != Status::SUCCESS) return;
- if (subsystems.size() > 0) {
- for (size_t i = 0; i < subsystems.size(); i++) {
- const PowerStateSubsystem& subsystem = subsystems[i];
- for (size_t j = 0; j < subsystem.states.size(); j++) {
- const PowerStateSubsystemSleepState& state = subsystem.states[j];
- auto subsystemStatePtr = make_shared<LogEvent>(
- android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
- subsystemStatePtr->write(subsystem.name);
- subsystemStatePtr->write(state.name);
- subsystemStatePtr->write(state.residencyInMsecSinceBoot);
- subsystemStatePtr->write(state.totalTransitions);
- subsystemStatePtr->write(state.lastEntryTimestampMs);
- subsystemStatePtr->write(state.supportedOnlyInSuspend);
- subsystemStatePtr->init();
- data->push_back(subsystemStatePtr);
- VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
- subsystem.name.c_str(), state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions,
- (long long)state.lastEntryTimestampMs);
- }
+ for (size_t i = 0; i < states.size(); i++) {
+ const PowerStatePlatformSleepState& state = states[i];
+
+ auto statePtr = make_shared<LogEvent>(android::util::PLATFORM_SLEEP_STATE,
+ timestamp);
+ statePtr->write(state.name);
+ statePtr->write(state.residencyInMsecSinceBoot);
+ statePtr->write(state.totalTransitions);
+ statePtr->write(state.supportedOnlyInSuspend);
+ statePtr->init();
+ data->push_back(statePtr);
+ VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
+ (long long)state.residencyInMsecSinceBoot,
+ (long long)state.totalTransitions,
+ state.supportedOnlyInSuspend ? 1 : 0);
+ for (auto voter : state.voters) {
+ auto voterPtr = make_shared<LogEvent>(android::util::SLEEP_STATE_VOTER,
+ timestamp);
+ voterPtr->write(state.name);
+ voterPtr->write(voter.name);
+ voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
+ voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
+ voterPtr->init();
+ data->push_back(voterPtr);
+ VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
+ voter.name.c_str(),
+ (long long)voter.totalTimeInMsecVotedForSinceBoot,
+ (long long)voter.totalNumberOfTimesVotedSinceBoot);
}
}
});
+ if (!ret.isOk()) {
+ ALOGE("getLowPowerStats() failed: power HAL service not available");
+ gPowerHalV1_0 = nullptr;
+ return false;
+ }
+ }
+
+ if (mTagId == android::util::SUBSYSTEM_SLEEP_STATE) {
+ // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
+ sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
+ android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
+ if (gPowerHal_1_1 != nullptr) {
+ ret = gPowerHal_1_1->getSubsystemLowPowerStats(
+ [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+ if (status != Status::SUCCESS) return;
+
+ if (subsystems.size() > 0) {
+ for (size_t i = 0; i < subsystems.size(); i++) {
+ const PowerStateSubsystem& subsystem = subsystems[i];
+ for (size_t j = 0; j < subsystem.states.size(); j++) {
+ const PowerStateSubsystemSleepState& state =
+ subsystem.states[j];
+ auto subsystemStatePtr = make_shared<LogEvent>(
+ android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
+ subsystemStatePtr->write(subsystem.name);
+ subsystemStatePtr->write(state.name);
+ subsystemStatePtr->write(state.residencyInMsecSinceBoot);
+ subsystemStatePtr->write(state.totalTransitions);
+ subsystemStatePtr->write(state.lastEntryTimestampMs);
+ subsystemStatePtr->write(state.supportedOnlyInSuspend);
+ subsystemStatePtr->init();
+ data->push_back(subsystemStatePtr);
+ VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
+ subsystem.name.c_str(), state.name.c_str(),
+ (long long)state.residencyInMsecSinceBoot,
+ (long long)state.totalTransitions,
+ (long long)state.lastEntryTimestampMs);
+ }
+ }
+ }
+ });
+ }
}
return true;
}
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.h b/cmds/statsd/src/external/ResourcePowerManagerPuller.h
index c396c12..3399408 100644
--- a/cmds/statsd/src/external/ResourcePowerManagerPuller.h
+++ b/cmds/statsd/src/external/ResourcePowerManagerPuller.h
@@ -28,7 +28,8 @@
*/
class ResourcePowerManagerPuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
+ ResourcePowerManagerPuller(int tagId);
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index ffe1be9..b955f1c 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -22,6 +22,7 @@
#include <private/android_filesystem_config.h>
#include "StatsCompanionServicePuller.h"
#include "StatsService.h"
+#include "guardrail/StatsdStats.h"
using namespace android;
using namespace android::base;
@@ -39,13 +40,16 @@
// The reading and parsing are implemented in Java. It is not difficult to port over. But for now
// let StatsCompanionService handle that and send the data back.
-bool StatsCompanionServicePuller::Pull(const int tagId, vector<shared_ptr<LogEvent> >* data) {
+StatsCompanionServicePuller::StatsCompanionServicePuller(int tagId) : StatsPuller(tagId) {
+}
+
+bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* data) {
sp<IStatsCompanionService> statsCompanion = StatsService::getStatsCompanionService();
vector<StatsLogEventWrapper> returned_value;
if (statsCompanion != NULL) {
- Status status = statsCompanion->pullData(tagId, &returned_value);
+ Status status = statsCompanion->pullData(mTagId, &returned_value);
if (!status.isOk()) {
- ALOGW("error pulling for %d", tagId);
+ ALOGW("error pulling for %d", mTagId);
return false;
}
data->clear();
@@ -60,7 +64,7 @@
std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize);
data->push_back(make_shared<LogEvent>(tmp));
}
- ALOGD("StatsCompanionServicePuller::pull succeeded for %d", tagId);
+ ALOGD("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
return true;
} else {
ALOGW("statsCompanion not found!");
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.h b/cmds/statsd/src/external/StatsCompanionServicePuller.h
index 3ff2274..4c91f31 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.h
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.h
@@ -25,7 +25,8 @@
class StatsCompanionServicePuller : public StatsPuller {
public:
- bool Pull(const int tagId, vector<std::shared_ptr<LogEvent> >* data) override;
+ StatsCompanionServicePuller(int tagId);
+ bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
new file mode 100644
index 0000000..cadc535
--- /dev/null
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include "StatsPuller.h"
+#include "guardrail/StatsdStats.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::lock_guard;
+
+// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
+StatsPuller::StatsPuller(const int tagId)
+ : mTagId(tagId) {
+ if (StatsdStats::kPullerCooldownMap.find(tagId) == StatsdStats::kPullerCooldownMap.end()) {
+ mCoolDownSec = StatsdStats::kDefaultPullerCooldown;
+ } else {
+ mCoolDownSec = StatsdStats::kPullerCooldownMap[tagId];
+ }
+ VLOG("Puller for tag %d created. Cooldown set to %ld", mTagId, mCoolDownSec);
+}
+
+bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
+ lock_guard<std::mutex> lock(mLock);
+ StatsdStats::getInstance().notePull(mTagId);
+ long curTime = time(nullptr);
+ if (curTime - mLastPullTimeSec < mCoolDownSec) {
+ (*data) = mCachedData;
+ StatsdStats::getInstance().notePullFromCache(mTagId);
+ return true;
+ }
+ if (mMinPullIntervalSec > curTime - mLastPullTimeSec) {
+ mMinPullIntervalSec = curTime - mLastPullTimeSec;
+ StatsdStats::getInstance().updateMinPullIntervalSec(mTagId, mMinPullIntervalSec);
+ }
+ mCachedData.clear();
+ mLastPullTimeSec = curTime;
+ bool ret = PullInternal(&mCachedData);
+ if (ret) {
+ (*data) = mCachedData;
+ }
+ return ret;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index 940ad9c..47cc9f0 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -18,11 +18,13 @@
#include <android/os/StatsLogEventWrapper.h>
#include <utils/String16.h>
+#include <mutex>
#include <vector>
+
#include "logd/LogEvent.h"
+#include "guardrail/StatsdStats.h"
using android::os::StatsLogEventWrapper;
-using std::vector;
namespace android {
namespace os {
@@ -30,9 +32,33 @@
class StatsPuller {
public:
- virtual ~StatsPuller(){};
+ StatsPuller(const int tagId);
- virtual bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) = 0;
+ virtual ~StatsPuller() {}
+
+ bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
+
+protected:
+ // The atom tag id this puller pulls
+ const int mTagId;
+
+private:
+ mutable std::mutex mLock;
+ // Minimum time before this puller does actual pull again.
+ // If a pull request comes before cooldown, a cached version from purevious pull
+ // will be returned.
+ // The actual value should be determined by individual pullers.
+ long mCoolDownSec;
+ // For puller stats
+ long mMinPullIntervalSec = LONG_MAX;
+
+ virtual bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) = 0;
+
+ // Cache of data from last pull. If next request comes before cool down finishes,
+ // cached data will be returned.
+ std::vector<std::shared_ptr<LogEvent>> mCachedData;
+
+ long mLastPullTimeSec;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index d707f85..58c7b12 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -45,29 +45,29 @@
StatsPullerManagerImpl::StatsPullerManagerImpl()
: mCurrentPullingInterval(LONG_MAX) {
- shared_ptr<StatsPuller> statsCompanionServicePuller = make_shared<StatsCompanionServicePuller>();
- shared_ptr<StatsPuller> resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
- shared_ptr<StatsPuller> cpuTimePerUidPuller = make_shared<CpuTimePerUidPuller>();
- shared_ptr<StatsPuller> cpuTimePerUidFreqPuller = make_shared<CpuTimePerUidFreqPuller>();
-
mPullers.insert({android::util::KERNEL_WAKELOCK,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(android::util::KERNEL_WAKELOCK)});
mPullers.insert({android::util::WIFI_BYTES_TRANSFER,
- statsCompanionServicePuller});
- mPullers.insert({android::util::MOBILE_BYTES_TRANSFER,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(android::util::WIFI_BYTES_TRANSFER)});
+ mPullers.insert(
+ {android::util::MOBILE_BYTES_TRANSFER,
+ make_shared<StatsCompanionServicePuller>(android::util::MOBILE_BYTES_TRANSFER)});
mPullers.insert({android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(
+ android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)});
mPullers.insert({android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
- statsCompanionServicePuller});
+ make_shared<StatsCompanionServicePuller>(
+ android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)});
mPullers.insert({android::util::PLATFORM_SLEEP_STATE,
- resourcePowerManagerPuller});
+ make_shared<ResourcePowerManagerPuller>(android::util::PLATFORM_SLEEP_STATE)});
mPullers.insert({android::util::SLEEP_STATE_VOTER,
- resourcePowerManagerPuller});
- mPullers.insert({android::util::SUBSYSTEM_SLEEP_STATE,
- resourcePowerManagerPuller});
- mPullers.insert({android::util::CPU_TIME_PER_UID, cpuTimePerUidPuller});
- mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, cpuTimePerUidFreqPuller});
+ make_shared<ResourcePowerManagerPuller>(android::util::SLEEP_STATE_VOTER)});
+ mPullers.insert(
+ {android::util::SUBSYSTEM_SLEEP_STATE,
+ make_shared<ResourcePowerManagerPuller>(android::util::SUBSYSTEM_SLEEP_STATE)});
+ mPullers.insert({android::util::CPU_TIME_PER_FREQ, make_shared<StatsCompanionServicePuller>(android::util::CPU_TIME_PER_FREQ)});
+ mPullers.insert({android::util::CPU_TIME_PER_UID, make_shared<CpuTimePerUidPuller>()});
+ mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, make_shared<CpuTimePerUidFreqPuller>()});
mStatsCompanionService = StatsService::getStatsCompanionService();
}
@@ -76,7 +76,7 @@
if (DEBUG) ALOGD("Initiating pulling %d", tagId);
if (mPullers.find(tagId) != mPullers.end()) {
- bool ret = mPullers.find(tagId)->second->Pull(tagId, data);
+ bool ret = mPullers.find(tagId)->second->Pull(data);
ALOGD("pulled %d items", (int)data->size());
return ret;
} else {
diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp
index d10e167..4ff4f74 100644
--- a/cmds/statsd/src/field_util.cpp
+++ b/cmds/statsd/src/field_util.cpp
@@ -184,6 +184,7 @@
}
}
+namespace {
void findFields(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
@@ -287,9 +288,18 @@
}
}
+} // namespace
+
+void findFields(
+ const FieldValueMap& fieldValueMap,
+ const FieldMatcher& matcher,
+ std::vector<Field>* rootFields) {
+ return findFields(fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), rootFields);
+}
+
void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) {
std::vector<Field> rootFields;
- findFields(*fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), &rootFields);
+ findFields(*fieldValueMap, matcher, &rootFields);
std::set<Field, FieldCmp> rootFieldSet(rootFields.begin(), rootFields.end());
auto it = fieldValueMap->begin();
while (it != fieldValueMap->end()) {
@@ -313,6 +323,11 @@
return true;
}
+bool IsAttributionUidField(const Field& field) {
+ return field.child_size() == 1 && field.child(0).field() == 1
+ && field.child(0).child_size() == 1 && field.child(0).child(0).field() == 1;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h
index 3e7d54c..a4dfddd 100644
--- a/cmds/statsd/src/field_util.h
+++ b/cmds/statsd/src/field_util.h
@@ -85,6 +85,9 @@
// Filter out the fields not in the field matcher.
void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap);
+// Returns if the field is attribution node uid field.
+bool IsAttributionUidField(const Field& field);
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 33927aa..36dd616 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -19,6 +19,7 @@
#include "StatsdStats.h"
#include <android/util/ProtoOutputStream.h>
+#include "../stats_log_util.h"
#include "statslog.h"
namespace android {
@@ -59,6 +60,20 @@
const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
+std::map<int, long> StatsdStats::kPullerCooldownMap = {
+ {android::util::KERNEL_WAKELOCK, 1},
+ {android::util::WIFI_BYTES_TRANSFER, 1},
+ {android::util::MOBILE_BYTES_TRANSFER, 1},
+ {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 1},
+ {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 1},
+ {android::util::PLATFORM_SLEEP_STATE, 1},
+ {android::util::SLEEP_STATE_VOTER, 1},
+ {android::util::SUBSYSTEM_SLEEP_STATE, 1},
+ {android::util::CPU_TIME_PER_FREQ, 1},
+ {android::util::CPU_TIME_PER_UID, 1},
+ {android::util::CPU_TIME_PER_UID_FREQ, 1},
+};
+
// TODO: add stats for pulled atoms.
StatsdStats::StatsdStats() {
mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
@@ -70,6 +85,14 @@
return statsInstance;
}
+void StatsdStats::addToIceBoxLocked(const StatsdStatsReport_ConfigStats& stats) {
+ // The size of mIceBox grows strictly by one at a time. It won't be > kMaxIceBoxSize.
+ if (mIceBox.size() == kMaxIceBoxSize) {
+ mIceBox.pop_front();
+ }
+ mIceBox.push_back(stats);
+}
+
void StatsdStats::noteConfigReceived(const ConfigKey& key, int metricsCount, int conditionsCount,
int matchersCount, int alertsCount, bool isValid) {
lock_guard<std::mutex> lock(mLock);
@@ -92,7 +115,7 @@
mConfigStats[key] = configStats;
} else {
configStats.set_deletion_time_sec(nowTimeSec);
- mIceBox.push_back(configStats);
+ addToIceBoxLocked(configStats);
}
}
@@ -108,7 +131,7 @@
mMetricsStats.erase(key);
mAlertStats.erase(key);
mConditionStats.erase(key);
- mIceBox.push_back(it->second);
+ addToIceBoxLocked(it->second);
mConfigStats.erase(it);
}
}
@@ -231,6 +254,21 @@
mAnomalyAlarmRegisteredStats++;
}
+void StatsdStats::updateMinPullIntervalSec(int pullAtomId, long intervalSec) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].minPullIntervalSec = intervalSec;
+}
+
+void StatsdStats::notePull(int pullAtomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].totalPull++;
+}
+
+void StatsdStats::notePullFromCache(int pullAtomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[pullAtomId].totalPullFromCache++;
+}
+
void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
@@ -401,7 +439,7 @@
configStats.clear_alert_stats();
}
- VLOG("********Atom stats***********");
+ VLOG("********Pushed Atom stats***********");
const size_t atomCounts = mPushedAtomStats.size();
for (size_t i = 2; i < atomCounts; i++) {
if (mPushedAtomStats[i] > 0) {
@@ -415,6 +453,12 @@
}
}
+ VLOG("********Pulled Atom stats***********");
+ for (const auto& pair : mPulledAtomStats) {
+ android::os::statsd::writePullerStatsToStream(pair, &proto);
+ VLOG("Atom %d->%ld, %ld, %ld\n", (int) pair.first, (long) pair.second.totalPull, (long) pair.second.totalPullFromCache, (long) pair.second.minPullIntervalSec);
+ }
+
if (mAnomalyAlarmRegisteredStats > 0) {
VLOG("********AnomalyAlarmStats stats***********");
long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 45aa192..52ab253 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -17,9 +17,11 @@
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include "statslog.h"
#include <gtest/gtest_prod.h>
#include <log/log_time.h>
+#include <list>
#include <mutex>
#include <string>
#include <vector>
@@ -44,6 +46,9 @@
const static int kMaxMetricCountPerConfig = 300;
const static int kMaxMatcherCountPerConfig = 500;
+ // The max number of old config stats we keep.
+ const static int kMaxIceBoxSize = 20;
+
const static int kMaxTimestampCount = 20;
const static int kMaxLogSourceCount = 50;
@@ -62,6 +67,13 @@
/* Min period between two checks of byte size per config key in nanoseconds. */
static const unsigned long long kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
+ // Default minimum interval between pulls for an atom. Pullers can return cached values if
+ // another pull request happens within this interval.
+ static std::map<int, long> kPullerCooldownMap;
+
+ // Default cooldown time for a puller
+ static const long kDefaultPullerCooldown = 1;
+
/**
* Report a new config has been received and report the static stats about the config.
*
@@ -154,6 +166,15 @@
void setUidMapChanges(int changes);
void setCurrentUidMapMemory(int bytes);
+ // Update minimum interval between pulls for an pulled atom
+ void updateMinPullIntervalSec(int pullAtomId, long intervalSec);
+
+ // Notify pull request for an atom
+ void notePull(int pullAtomId);
+
+ // Notify pull request for an atom served from cached data
+ void notePullFromCache(int pullAtomId);
+
/**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
@@ -168,6 +189,12 @@
*/
void dumpStats(std::vector<uint8_t>* buffer, bool reset);
+ typedef struct {
+ long totalPull;
+ long totalPullFromCache;
+ long minPullIntervalSec;
+ } PulledAtomStats;
+
private:
StatsdStats();
@@ -179,19 +206,21 @@
StatsdStatsReport_UidMapStats mUidMapStats;
// The stats about the configs that are still in use.
+ // The map size is capped by kMaxConfigCount.
std::map<const ConfigKey, StatsdStatsReport_ConfigStats> mConfigStats;
// Stores the stats for the configs that are no longer in use.
- std::vector<const StatsdStatsReport_ConfigStats> mIceBox;
+ // The size of the vector is capped by kMaxIceBoxSize.
+ std::list<const StatsdStatsReport_ConfigStats> mIceBox;
// Stores the number of output tuple of condition trackers when it's bigger than
// kDimensionKeySizeSoftLimit. When you see the number is kDimensionKeySizeHardLimit +1,
- // it means some data has been dropped.
+ // it means some data has been dropped. The map size is capped by kMaxConfigCount.
std::map<const ConfigKey, std::map<const int64_t, int>> mConditionStats;
// Stores the number of output tuple of metric producers when it's bigger than
// kDimensionKeySizeSoftLimit. When you see the number is kDimensionKeySizeHardLimit +1,
- // it means some data has been dropped.
+ // it means some data has been dropped. The map size is capped by kMaxConfigCount.
std::map<const ConfigKey, std::map<const int64_t, int>> mMetricsStats;
// Stores the number of times a pushed atom is logged.
@@ -200,15 +229,18 @@
// This is a vector, not a map because it will be accessed A LOT -- for each stats log.
std::vector<int> mPushedAtomStats;
+ // Maps PullAtomId to its stats. The size is capped by the puller atom counts.
+ std::map<int, PulledAtomStats> mPulledAtomStats;
+
// Stores the number of times statsd modified the anomaly alarm registered with
// StatsCompanionService.
int mAnomalyAlarmRegisteredStats = 0;
// Stores the number of times an anomaly detection alert has been declared
- // (per config, per alert name).
+ // (per config, per alert name). The map size is capped by kMaxConfigCount.
std::map<const ConfigKey, std::map<const int64_t, int>> mAlertStats;
- // Stores how many times a matcher have been matched.
+ // Stores how many times a matcher have been matched. The map size is capped by kMaxConfigCount.
std::map<const ConfigKey, std::map<const int64_t, int>> mMatcherStats;
void noteConfigRemovedInternalLocked(const ConfigKey& key);
@@ -224,6 +256,8 @@
void noteBroadcastSent(const ConfigKey& key, int32_t timeSec);
+ void addToIceBoxLocked(const StatsdStatsReport_ConfigStats& stats);
+
FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestConfigRemove);
@@ -235,4 +269,4 @@
} // namespace statsd
} // namespace os
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 49a6e33..6782f3f 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -397,6 +397,14 @@
return dimensionsValue;
}
+DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) {
+ auto it = mFieldValueMap.find(field);
+ if (it == mFieldValueMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
string LogEvent::ToString() const {
ostringstream result;
result << "{ " << mTimestampNs << " (" << mTagId << ")";
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 8f3dedf..fdfa32e 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -132,6 +132,11 @@
return mFieldValueMap.size();
}
+ /**
+ * Returns the mutable DimensionsValue proto for the specific the field.
+ */
+ DimensionsValue* findFieldValueOrNull(const Field& field);
+
inline const FieldValueMap& getFieldValueMap() const { return mFieldValueMap; }
private:
diff --git a/cmds/statsd/src/logd/LogListener.h b/cmds/statsd/src/logd/LogListener.h
index 9641226..69ca571 100644
--- a/cmds/statsd/src/logd/LogListener.h
+++ b/cmds/statsd/src/logd/LogListener.h
@@ -33,7 +33,7 @@
LogListener();
virtual ~LogListener();
- virtual void OnLogEvent(const LogEvent& msg) = 0;
+ virtual void OnLogEvent(LogEvent* msg) = 0;
};
} // namespace statsd
diff --git a/cmds/statsd/src/logd/LogReader.cpp b/cmds/statsd/src/logd/LogReader.cpp
index c441a5e..7636268 100644
--- a/cmds/statsd/src/logd/LogReader.cpp
+++ b/cmds/statsd/src/logd/LogReader.cpp
@@ -110,7 +110,7 @@
LogEvent event(msg);
// Call the listener
- mListener->OnLogEvent(event);
+ mListener->OnLogEvent(&event);
}
}
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 46d9b92..48f62e7 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -93,11 +93,6 @@
return matched;
}
-bool IsAttributionUidField(const Field& field) {
- return field.child_size() == 1 && field.child(0).field() == 1
- && field.child(0).child_size() == 1 && field.child(0).child(0).field() == 1;
-}
-
bool matchesNonRepeatedField(
const UidMap& uidMap,
const FieldValueMap& fieldMap,
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 6087ae5..16fc7ee 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -84,7 +84,7 @@
FRIEND_TEST(CountMetricProducerTest, TestNonDimensionalEvents);
FRIEND_TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition);
FRIEND_TEST(CountMetricProducerTest, TestEventsWithSlicedCondition);
- FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetection);
+ FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 3f8a8ff..b546297 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -117,11 +117,11 @@
case DurationMetric_AggregationType_SUM:
return make_unique<OringDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
- mCurrentBucketStartTimeNs, mBucketSizeNs, mAnomalyTrackers);
+ mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
case DurationMetric_AggregationType_MAX_SPARSE:
return make_unique<MaxDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
- mCurrentBucketStartTimeNs, mBucketSizeNs, mAnomalyTrackers);
+ mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
}
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index e6f311b..1a4888c 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -326,6 +326,7 @@
}
}
+ mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
// Adjusts the bucket start time
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index a03047f..08b0981 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -140,6 +140,7 @@
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
+ FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 842581e..371460e 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -62,7 +62,7 @@
public:
DurationTracker(const ConfigKey& key, const int64_t& id, const HashableDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
- uint64_t currentBucketStartNs, uint64_t bucketSizeNs,
+ uint64_t currentBucketStartNs, uint64_t bucketSizeNs, bool conditionSliced,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: mConfigKey(key),
mTrackerId(id),
@@ -74,6 +74,7 @@
mCurrentBucketStartTimeNs(currentBucketStartNs),
mDuration(0),
mCurrentBucketNum(0),
+ mConditionSliced(conditionSliced),
mAnomalyTrackers(anomalyTrackers){};
virtual ~DurationTracker(){};
@@ -163,10 +164,13 @@
uint64_t mCurrentBucketNum;
+ const bool mConditionSliced;
+
std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 94f98ad..0c99391 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -28,9 +28,10 @@
const HashableDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
uint64_t currentBucketStartNs, uint64_t bucketSizeNs,
+ bool conditionSliced,
const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
- bucketSizeNs, anomalyTrackers) {
+ bucketSizeNs, conditionSliced, anomalyTrackers) {
}
bool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) {
@@ -63,7 +64,9 @@
}
DurationInfo& duration = mInfos[key];
- duration.conditionKeys = conditionKey;
+ if (mConditionSliced) {
+ duration.conditionKeys = conditionKey;
+ }
VLOG("MaxDuration: key %s start condition %d", key.c_str(), condition);
switch (duration.state) {
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 68c48cb1..5d3c158 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -31,7 +31,7 @@
MaxDurationTracker(const ConfigKey& key, const int64_t& id,
const HashableDimensionKey& eventKey, sp<ConditionWizard> wizard,
int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
- uint64_t bucketSizeNs,
+ uint64_t bucketSizeNs, bool conditionSliced,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
const ConditionKey& conditionKey) override;
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index c77d0b7..6bf4228 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -27,10 +27,10 @@
OringDurationTracker::OringDurationTracker(
const ConfigKey& key, const int64_t& id, const HashableDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
- uint64_t bucketSizeNs, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
-
+ uint64_t bucketSizeNs, bool conditionSliced,
+ const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
- bucketSizeNs, anomalyTrackers),
+ bucketSizeNs, conditionSliced, anomalyTrackers),
mStarted(),
mPaused() {
mLastStartTime = 0;
@@ -73,7 +73,7 @@
mPaused[key]++;
}
- if (mConditionKeyMap.find(key) == mConditionKeyMap.end()) {
+ if (mConditionSliced && mConditionKeyMap.find(key) == mConditionKeyMap.end()) {
mConditionKeyMap[key] = conditionKey;
}
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 7fe649c..638b7ad 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -30,7 +30,7 @@
OringDurationTracker(const ConfigKey& key, const int64_t& id,
const HashableDimensionKey& eventKey, sp<ConditionWizard> wizard,
int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
- uint64_t bucketSizeNs,
+ uint64_t bucketSizeNs, bool conditionSliced,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
@@ -67,7 +67,8 @@
FRIEND_TEST(OringDurationTrackerTest, TestCrossBucketBoundary);
FRIEND_TEST(OringDurationTrackerTest, TestDurationConditionChange);
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
};
} // namespace statsd
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 517d21d..b0c3197 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -269,7 +269,7 @@
}
}
-int UidMap::getParentUidOrSelf(int uid) {
+int UidMap::getHostUidOrSelf(int uid) const {
lock_guard<mutex> lock(mIsolatedMutex);
auto it = mIsolatedUidMap.find(uid);
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 07e13e0..4e37977 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -90,8 +90,8 @@
void assignIsolatedUid(int isolatedUid, int parentUid);
void removeIsolatedUid(int isolatedUid, int parentUid);
- // Returns the parent uid if it exists. Otherwise, returns the same uid that was passed-in.
- int getParentUidOrSelf(int uid);
+ // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
+ int getHostUidOrSelf(int uid) const;
// Gets the output. If every config key has received the output, then the output is cleared.
UidMapping getOutput(const ConfigKey& key);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index ae69a50..2596a5f 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -246,4 +246,12 @@
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;
}
\ No newline at end of file
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index b335b58..a41f30c 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -45,6 +45,13 @@
// for MessageValue Proto
const int FIELD_ID_FIELD_VALUE_IN_MESSAGE_VALUE_PROTO = 1;
+// for PulledAtomStats proto
+const int FIELD_ID_PULLED_ATOM_STATS = 10;
+const int FIELD_ID_PULL_ATOM_ID = 1;
+const int FIELD_ID_TOTAL_PULL = 2;
+const int FIELD_ID_TOTAL_PULL_FROM_CACHE = 3;
+const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4;
+
void writeDimensionsValueProtoToStream(const DimensionsValue& dimensionsValue,
ProtoOutputStream* protoOutput) {
protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, dimensionsValue.field());
@@ -248,6 +255,19 @@
}
}
+void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
+ util::ProtoOutputStream* protoOutput) {
+ long long token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_PULLED_ATOM_STATS |
+ FIELD_COUNT_REPEATED);
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_PULL_ATOM_ID, (int32_t)pair.first);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL, (long long)pair.second.totalPull);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL_FROM_CACHE,
+ (long long)pair.second.totalPullFromCache);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_PULL_INTERVAL_SEC,
+ (long long)pair.second.minPullIntervalSec);
+ protoOutput->end(token);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 33303dc..09a43f5 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -17,29 +17,32 @@
#pragma once
#include <android/util/ProtoOutputStream.h>
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "field_util.h"
+#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "guardrail/StatsdStats.h"
namespace android {
namespace os {
namespace statsd {
// Helper function to write DimensionsValue proto to ProtoOutputStream.
-void writeDimensionsValueProtoToStream(
- const DimensionsValue& fieldValue, util::ProtoOutputStream* protoOutput);
+void writeDimensionsValueProtoToStream(const DimensionsValue& fieldValue,
+ util::ProtoOutputStream* protoOutput);
// Helper function to write Field proto to ProtoOutputStream.
-void writeFieldProtoToStream(
- const Field& field, util::ProtoOutputStream* protoOutput);
+void writeFieldProtoToStream(const Field& field, util::ProtoOutputStream* protoOutput);
// Helper function to construct the field value tree and write to ProtoOutputStream
-void writeFieldValueTreeToStream(const FieldValueMap &fieldValueMap,
- util::ProtoOutputStream* protoOutput);
+void writeFieldValueTreeToStream(const FieldValueMap& fieldValueMap,
+ util::ProtoOutputStream* protoOutput);
// Convert the TimeUnit enum to the bucket size in millis.
int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit);
+// Helper function to write PulledAtomStats to ProtoOutputStream
+void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
+ util::ProtoOutputStream* protoOutput);
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 5d053e2..aab5bed 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -60,9 +60,9 @@
// Expect only the first flush to trigger a check for byte size since the last two are
// rate-limited.
EXPECT_CALL(mockMetricsManager, byteSize()).Times(1);
- p.flushIfNecessary(99, key, mockMetricsManager);
- p.flushIfNecessary(100, key, mockMetricsManager);
- p.flushIfNecessary(101, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(99, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(100, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(101, key, mockMetricsManager);
}
TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
@@ -80,12 +80,12 @@
.WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
// Expect only one broadcast despite always returning a size that should trigger broadcast.
- p.flushIfNecessary(1, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(1, key, mockMetricsManager);
EXPECT_EQ(1, broadcastCount);
// This next call to flush should not trigger a broadcast.
p.mLastByteSizeTimes.clear(); // Force another check for byte size.
- p.flushIfNecessary(2, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(2, key, mockMetricsManager);
EXPECT_EQ(1, broadcastCount);
}
@@ -106,7 +106,7 @@
EXPECT_CALL(mockMetricsManager, onDumpReport(_)).Times(1);
// Expect to call the onDumpReport and skip the broadcast.
- p.flushIfNecessary(1, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(1, key, mockMetricsManager);
EXPECT_EQ(0, broadcastCount);
}
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 945af27..5292f24 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -45,18 +45,18 @@
addEvent.write(1); // Indicates creation.
addEvent.init();
- EXPECT_EQ(101, m->getParentUidOrSelf(101));
+ EXPECT_EQ(101, m->getHostUidOrSelf(101));
- p.OnLogEvent(addEvent);
- EXPECT_EQ(100, m->getParentUidOrSelf(101));
+ p.OnLogEvent(&addEvent);
+ EXPECT_EQ(100, m->getHostUidOrSelf(101));
LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
removeEvent.write(100); // parent UID
removeEvent.write(101); // isolated UID
removeEvent.write(0); // Indicates removal.
removeEvent.init();
- p.OnLogEvent(removeEvent);
- EXPECT_EQ(101, m->getParentUidOrSelf(101));
+ p.OnLogEvent(&removeEvent);
+ EXPECT_EQ(101, m->getHostUidOrSelf(101));
}
TEST(UidMapTest, TestMatching) {
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index 5842bc8..66bfa68 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -54,11 +54,73 @@
return bucket;
}
+// Returns the value, for the given key, in that bucket, or 0 if not present.
+int64_t getBucketValue(const std::shared_ptr<DimToValMap>& bucket,
+ const HashableDimensionKey& key) {
+ const auto& itr = bucket->find(key);
+ if (itr != bucket->end()) {
+ return itr->second;
+ }
+ return 0;
+}
+
+// Returns true if keys in trueList are detected as anomalies and keys in falseList are not.
+bool detectAnomaliesPass(AnomalyTracker& tracker,
+ const int64_t& bucketNum,
+ const std::shared_ptr<DimToValMap>& currentBucket,
+ const std::set<const HashableDimensionKey>& trueList,
+ const std::set<const HashableDimensionKey>& falseList) {
+ for (HashableDimensionKey key : trueList) {
+ if (!tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) {
+ return false;
+ }
+ }
+ for (HashableDimensionKey key : falseList) {
+ if (tracker.detectAnomaly(bucketNum, key, getBucketValue(currentBucket, key))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Calls tracker.detectAndDeclareAnomaly on each key in the bucket.
+void detectAndDeclareAnomalies(AnomalyTracker& tracker,
+ const int64_t& bucketNum,
+ const std::shared_ptr<DimToValMap>& bucket,
+ const int64_t& eventTimestamp) {
+ for (const auto& kv : *bucket) {
+ tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, kv.first, kv.second);
+ }
+}
+
+// Asserts that the refractory time for each key in timestamps is the corresponding
+// timestamp (in ns) + refractoryPeriodSec.
+// If a timestamp value is negative, instead asserts that the refractory period is inapplicable
+// (either non-existant or already past).
+void checkRefractoryTimes(AnomalyTracker& tracker,
+ const int64_t& currTimestampNs,
+ const int32_t& refractoryPeriodSec,
+ const std::unordered_map<HashableDimensionKey, int64_t>& timestamps) {
+ for (const auto& kv : timestamps) {
+ if (kv.second < 0) {
+ // Make sure that, if there is a refractory period, it is already past.
+ EXPECT_LT(tracker.getRefractoryPeriodEndsSec(kv.first),
+ currTimestampNs / NS_PER_SEC + 1)
+ << "Failure was at currTimestampNs " << currTimestampNs;
+ } else {
+ EXPECT_EQ(tracker.getRefractoryPeriodEndsSec(kv.first),
+ kv.second / NS_PER_SEC + refractoryPeriodSec)
+ << "Failure was at currTimestampNs " << currTimestampNs;
+ }
+ }
+}
+
TEST(AnomalyTrackerTest, TestConsecutiveBuckets) {
const int64_t bucketSizeNs = 30 * NS_PER_SEC;
+ const int32_t refractoryPeriodSec = 2 * bucketSizeNs / NS_PER_SEC;
Alert alert;
alert.set_num_buckets(3);
- alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
+ alert.set_refractory_period_secs(refractoryPeriodSec);
alert.set_trigger_if_sum_gt(2);
AnomalyTracker anomalyTracker(alert, kConfigKey);
@@ -66,26 +128,31 @@
HashableDimensionKey keyB = getMockDimensionKey(1, "b");
HashableDimensionKey keyC = getMockDimensionKey(1, "c");
- std::shared_ptr<DimToValMap> bucket0 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
- int64_t eventTimestamp0 = 10;
- std::shared_ptr<DimToValMap> bucket1 = MockBucket({{keyA, 1}});
- int64_t eventTimestamp1 = bucketSizeNs + 11;
- std::shared_ptr<DimToValMap> bucket2 = MockBucket({{keyB, 1}});
- int64_t eventTimestamp2 = 2 * bucketSizeNs + 12;
- std::shared_ptr<DimToValMap> bucket3 = MockBucket({{keyA, 2}});
- int64_t eventTimestamp3 = 3 * bucketSizeNs + 13;
- std::shared_ptr<DimToValMap> bucket4 = MockBucket({{keyB, 1}});
- int64_t eventTimestamp4 = 4 * bucketSizeNs + 14;
- std::shared_ptr<DimToValMap> bucket5 = MockBucket({{keyA, 2}});
- int64_t eventTimestamp5 = 5 * bucketSizeNs + 15;
- std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}});
- int64_t eventTimestamp6 = 6 * bucketSizeNs + 16;
+ int64_t eventTimestamp0 = 10 * NS_PER_SEC;
+ int64_t eventTimestamp1 = bucketSizeNs + 11 * NS_PER_SEC;
+ int64_t eventTimestamp2 = 2 * bucketSizeNs + 12 * NS_PER_SEC;
+ int64_t eventTimestamp3 = 3 * bucketSizeNs + 13 * NS_PER_SEC;
+ int64_t eventTimestamp4 = 4 * bucketSizeNs + 14 * NS_PER_SEC;
+ int64_t eventTimestamp5 = 5 * bucketSizeNs + 5 * NS_PER_SEC;
+ int64_t eventTimestamp6 = 6 * bucketSizeNs + 16 * NS_PER_SEC;
+ std::shared_ptr<DimToValMap> bucket0 = MockBucket({{keyA, 1}, {keyB, 2}, {keyC, 1}});
+ std::shared_ptr<DimToValMap> bucket1 = MockBucket({{keyA, 1}});
+ std::shared_ptr<DimToValMap> bucket2 = MockBucket({{keyB, 1}});
+ std::shared_ptr<DimToValMap> bucket3 = MockBucket({{keyA, 2}});
+ std::shared_ptr<DimToValMap> bucket4 = MockBucket({{keyB, 5}});
+ std::shared_ptr<DimToValMap> bucket5 = MockBucket({{keyA, 2}});
+ std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}});
+
+ // Start time with no events.
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(0, *bucket0));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp0, 0, *bucket0);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
+
+ // Event from bucket #0 occurs.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 0, bucket0, {}, {keyA, keyB, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 0, bucket0, eventTimestamp1);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp0, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}});
// Adds past bucket #0
anomalyTracker.addPastBucket(bucket0, 0);
@@ -94,9 +161,12 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 1, *bucket1);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
+
+ // Event from bucket #1 occurs.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 1, bucket1, {}, {keyA, keyB, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 1, bucket1, eventTimestamp1);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}});
// Adds past bucket #0 again. The sum does not change.
anomalyTracker.addPastBucket(bucket0, 0);
@@ -105,9 +175,10 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1 + 1, 1, *bucket1);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 1, bucket1, {}, {keyA, keyB, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 1, bucket1, eventTimestamp1 + 1);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}});
// Adds past bucket #1.
anomalyTracker.addPastBucket(bucket1, 1);
@@ -116,9 +187,12 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 2, *bucket2);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+
+ // Event from bucket #2 occurs. New anomaly on keyB.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 2, bucket2, {keyB}, {keyA, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 2, bucket2, eventTimestamp2);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}});
// Adds past bucket #1 again. Nothing changes.
anomalyTracker.addPastBucket(bucket1, 1);
@@ -127,9 +201,11 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2 + 1, 2, *bucket2);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+ // Event from bucket #2 occurs (again).
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 2, bucket2, {keyB}, {keyA, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 2, bucket2, eventTimestamp2 + 1);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}});
// Adds past bucket #2.
anomalyTracker.addPastBucket(bucket2, 2);
@@ -137,10 +213,12 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(3, *bucket3));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 3, *bucket3);
- // Within refractory period.
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+
+ // Event from bucket #3 occurs. New anomaly on keyA.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 3, bucket3, {keyA}, {keyB, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 3, bucket3, eventTimestamp3);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp3, refractoryPeriodSec,
+ {{keyA, eventTimestamp3}, {keyB, eventTimestamp2}, {keyC, -1}});
// Adds bucket #3.
anomalyTracker.addPastBucket(bucket3, 3L);
@@ -148,37 +226,46 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(4, *bucket4));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 4, *bucket4);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+
+ // Event from bucket #4 occurs. New anomaly on keyB.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 4, bucket4, {keyB}, {keyA, keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 4, bucket4, eventTimestamp4);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp4, refractoryPeriodSec,
+ {{keyA, eventTimestamp3}, {keyB, eventTimestamp4}, {keyC, -1}});
// Adds bucket #4.
anomalyTracker.addPastBucket(bucket4, 4);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 4L);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
- EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(5, *bucket5));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 5, *bucket5);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
+ EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL);
+
+ // Event from bucket #5 occurs. New anomaly on keyA, which is still in refractory.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 5, bucket5, {keyA, keyB}, {keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 5, bucket5, eventTimestamp5);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp5, refractoryPeriodSec,
+ {{keyA, eventTimestamp3}, {keyB, eventTimestamp4}, {keyC, -1}});
// Adds bucket #5.
anomalyTracker.addPastBucket(bucket5, 5);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 5L);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
- EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(6, *bucket6));
- // Within refractory period.
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 6, *bucket6);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
+ EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL);
+
+ // Event from bucket #6 occurs. New anomaly on keyA, which is now out of refractory.
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 6, bucket6, {keyA, keyB}, {keyC}));
+ detectAndDeclareAnomalies(anomalyTracker, 6, bucket6, eventTimestamp6);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec,
+ {{keyA, eventTimestamp6}, {keyB, eventTimestamp4}, {keyC, -1}});
}
TEST(AnomalyTrackerTest, TestSparseBuckets) {
const int64_t bucketSizeNs = 30 * NS_PER_SEC;
+ const int32_t refractoryPeriodSec = 2 * bucketSizeNs / NS_PER_SEC;
Alert alert;
alert.set_num_buckets(3);
- alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
+ alert.set_refractory_period_secs(refractoryPeriodSec);
alert.set_trigger_if_sum_gt(2);
AnomalyTracker anomalyTracker(alert, kConfigKey);
@@ -204,9 +291,10 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(9, *bucket9));
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 9, *bucket9);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1);
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 9, bucket9, {}, {keyA, keyB, keyC, keyD}));
+ detectAndDeclareAnomalies(anomalyTracker, 9, bucket9, eventTimestamp1);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Add past bucket #9
anomalyTracker.addPastBucket(bucket9, 9);
@@ -215,25 +303,27 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(16, *bucket16));
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 16, bucket16, {keyB}, {keyA, keyC, keyD}));
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 16, *bucket16);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+ detectAndDeclareAnomalies(anomalyTracker, 16, bucket16, eventTimestamp2);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Add past bucket #16
anomalyTracker.addPastBucket(bucket16, 16);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 16L);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(18, *bucket18));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 18, bucket18, {keyB}, {keyA, keyC, keyD}));
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
// Within refractory period.
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 18, *bucket18);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
+ detectAndDeclareAnomalies(anomalyTracker, 18, bucket18, eventTimestamp3);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp3, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
@@ -243,13 +333,14 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD}));
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 20, *bucket20);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
+ detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp4, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Add bucket #18 again. Nothing changes.
anomalyTracker.addPastBucket(bucket18, 18);
@@ -257,13 +348,14 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_TRUE(anomalyTracker.detectAnomaly(20, *bucket20));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD}));
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4 + 1, 20, *bucket20);
+ detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4 + 1);
// Within refractory period.
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp4 + 1, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Add past bucket #20
anomalyTracker.addPastBucket(bucket20, 20);
@@ -271,32 +363,37 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 3LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(25, *bucket25));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 25, bucket25, {}, {keyA, keyB, keyC, keyD}));
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 25, *bucket25);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ detectAndDeclareAnomalies(anomalyTracker, 25, bucket25, eventTimestamp5);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp5, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Add past bucket #25
anomalyTracker.addPastBucket(bucket25, 25);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 25L);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyD), 1LL);
- EXPECT_FALSE(anomalyTracker.detectAnomaly(28, *bucket28));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {},
+ {keyA, keyB, keyC, keyD, keyE}));
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 28, *bucket28);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
// Updates current bucket #28.
(*bucket28)[keyE] = 5;
- EXPECT_TRUE(anomalyTracker.detectAnomaly(28, *bucket28));
+ EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {keyE},
+ {keyA, keyB, keyC, keyD}));
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6 + 7, 28, *bucket28);
- EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp6 + 7);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6 + 7);
+ // TODO: after detectAnomaly fix: EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+ checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec,
+ {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, eventTimestamp6 + 7}});
}
} // namespace statsd
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
new file mode 100644
index 0000000..39c9549
--- /dev/null
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -0,0 +1,201 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateStatsdConfig() {
+ StatsdConfig config;
+ auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+ auto attributionNodeMatcher =
+ wakelockAcquireMatcher.mutable_simple_atom_matcher()->add_field_value_matcher();
+ attributionNodeMatcher->set_field(1);
+ attributionNodeMatcher->set_position(Position::ANY);
+ auto uidMatcher = attributionNodeMatcher->mutable_matches_tuple()->add_field_value_matcher();
+ uidMatcher->set_field(1); // uid field.
+ uidMatcher->set_eq_string("com.android.gmscore");
+
+ *config.add_atom_matcher() = wakelockAcquireMatcher;
+
+ auto countMetric = config.add_count_metric();
+ countMetric->set_id(123456);
+ countMetric->set_what(wakelockAcquireMatcher.id());
+ *countMetric->mutable_dimensions() =
+ CreateAttributionUidAndTagDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ countMetric->set_bucket(ONE_MINUTE);
+ return config;
+}
+
+} // namespace
+
+TEST(AttributionE2eTest, TestAttributionMatchAndSlice) {
+ auto config = CreateStatsdConfig();
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+
+ ConfigKey cfgKey;
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ // Here it assumes that GMS core has two uids.
+ processor->getUidMap()->updateApp(
+ android::String16("com.android.gmscore"), 222 /* uid */, 1 /* version code*/);
+ processor->getUidMap()->updateApp(
+ android::String16("com.android.gmscore"), 444 /* uid */, 1 /* version code*/);
+ processor->getUidMap()->updateApp(
+ android::String16("app1"), 111 /* uid */, 2 /* version code*/);
+ processor->getUidMap()->updateApp(
+ android::String16("APP3"), 333 /* uid */, 2 /* version code*/);
+
+ // GMS core node is in the middle.
+ std::vector<AttributionNode> attributions1 =
+ {CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
+ CreateAttribution(333, "App3")};
+
+ // GMS core node is the last one.
+ std::vector<AttributionNode> attributions2 =
+ {CreateAttribution(111, "App1"), CreateAttribution(333, "App3"),
+ CreateAttribution(222, "GMSCoreModule1")};
+
+ // GMS core node is the first one.
+ std::vector<AttributionNode> attributions3 =
+ {CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
+
+ // Single GMS core node.
+ std::vector<AttributionNode> attributions4 =
+ {CreateAttribution(222, "GMSCoreModule1")};
+
+ // GMS core has another uid.
+ std::vector<AttributionNode> attributions5 =
+ {CreateAttribution(111, "App1"), CreateAttribution(444, "GMSCoreModule2"),
+ CreateAttribution(333, "App3")};
+
+ // Multiple GMS core nodes.
+ std::vector<AttributionNode> attributions6 =
+ {CreateAttribution(444, "GMSCoreModule2"), CreateAttribution(222, "GMSCoreModule1")};
+
+ // No GMS core nodes.
+ std::vector<AttributionNode> attributions7 =
+ {CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
+ std::vector<AttributionNode> attributions8 = {CreateAttribution(111, "App1")};
+
+ // GMS core node with isolated uid.
+ const int isolatedUid = 666;
+ std::vector<AttributionNode> attributions9 =
+ {CreateAttribution(isolatedUid, "GMSCoreModule3")};
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+ // Events 1~4 are in the 1st bucket.
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 2));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions2, "wl1", bucketStartTimeNs + 200));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+
+ // Events 5~8 are in the 3rd bucket.
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+ events.push_back(CreateAcquireWakelockEvent(
+ attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+ events.push_back(CreateIsolatedUidChangedEvent(
+ isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+ events.push_back(CreateIsolatedUidChangedEvent(
+ isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+
+ sortLogEventsByTimestamp(&events);
+
+ for (const auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+ ConfigMetricsReportList reports;
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &reports);
+ EXPECT_EQ(reports.reports_size(), 1);
+ EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+ StatsLogReport::CountMetricDataWrapper countMetrics;
+ sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+ EXPECT_EQ(countMetrics.data_size(), 4);
+
+ auto data = countMetrics.data(0);
+ ValidateAttributionUidAndTagDimension(
+ data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).count(), 2);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).count(), 1);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+
+ data = countMetrics.data(1);
+ ValidateAttributionUidAndTagDimension(
+ data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+ EXPECT_EQ(data.bucket_info_size(), 2);
+ EXPECT_EQ(data.bucket_info(0).count(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).count(), 1);
+ EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+
+ data = countMetrics.data(2);
+ ValidateAttributionUidAndTagDimension(
+ data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule3");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).count(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
+
+ data = countMetrics.data(3);
+ ValidateAttributionUidAndTagDimension(
+ data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+ EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).count(), 1);
+ EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+ EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index cbcc36b..cdc4467 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -25,6 +25,7 @@
namespace statsd {
#ifdef __ANDROID__
+namespace {
StatsdConfig CreateStatsdConfig() {
StatsdConfig config;
@@ -92,6 +93,8 @@
dimensionCondition->add_child()->set_field(1); // uid field.
return config;
}
+} // namespace
+
TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks) {
auto config = CreateStatsdConfig();
@@ -185,7 +188,7 @@
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
- processor->OnLogEvent(*event);
+ processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &reports);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index 47e8a72..2783356 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -107,7 +107,7 @@
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
- processor->OnLogEvent(*event);
+ processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 768336b..c391513 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -191,13 +191,14 @@
EXPECT_EQ(1LL, bucketInfo.mCount);
}
-TEST(CountMetricProducerTest, TestAnomalyDetection) {
+TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
Alert alert;
alert.set_id(11);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(2);
alert.set_num_buckets(2);
- alert.set_refractory_period_secs(1);
+ const int32_t refPeriodSec = 1;
+ alert.set_refractory_period_secs(refPeriodSec);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -220,7 +221,7 @@
LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
- LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3 + NS_PER_SEC);
+ LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
// Two events in bucket #0.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
@@ -228,13 +229,13 @@
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
// One event in bucket #2. No alarm as bucket #0 is trashed out.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
// Two events in bucket #3.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
@@ -243,12 +244,14 @@
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event5.GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event5.GetTimestampNs() / NS_PER_SEC + refPeriodSec);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event7.GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event7.GetTimestampNs() / NS_PER_SEC + refPeriodSec);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index ad9c5a3..82772d8 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -201,6 +201,8 @@
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(25);
alert.set_num_buckets(2);
+ const int32_t refPeriodSec = 60;
+ alert.set_refractory_period_secs(refPeriodSec);
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert);
int tagId = 1;
@@ -213,10 +215,10 @@
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(13L,
gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
std::shared_ptr<LogEvent> event2 =
- std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 10);
+ std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
event2->write("some value");
event2->write(15);
event2->init();
@@ -225,19 +227,21 @@
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(15L,
gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event2->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
std::shared_ptr<LogEvent> event3 =
std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
event3->write("some value");
- event3->write(24);
+ event3->write(26);
event3->init();
gaugeProducer.onDataPulled({event3});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(24L,
+ EXPECT_EQ(26L,
gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event3->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
// The event4 does not have the gauge field. Thus the current bucket value is 0.
std::shared_ptr<LogEvent> event4 =
@@ -247,7 +251,6 @@
gaugeProducer.onDataPulled({event4});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second->empty());
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event3->GetTimestampNs());
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 704a466..0772b0d40 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -50,24 +50,22 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
- ConditionKey conditionKey1;
- conditionKey1[StringToId("condition")] = conditionKey;
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
- tracker.noteStart(key1, true, bucketStartTimeNs, conditionKey1);
+ tracker.noteStart(key1, true, bucketStartTimeNs, ConditionKey());
// Event starts again. This would not change anything as it already starts.
- tracker.noteStart(key1, true, bucketStartTimeNs + 3, conditionKey1);
+ tracker.noteStart(key1, true, bucketStartTimeNs + 3, ConditionKey());
// Stopped.
tracker.noteStop(key1, bucketStartTimeNs + 10, false);
// Another event starts in this bucket.
- tracker.noteStart(key2, true, bucketStartTimeNs + 20, conditionKey1);
+ tracker.noteStart(key2, true, bucketStartTimeNs + 20, ConditionKey());
tracker.noteStop(key2, bucketStartTimeNs + 40, false /*stop all*/);
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
@@ -80,20 +78,18 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
- ConditionKey conditionKey1;
- conditionKey1[StringToId("condition")] = conditionKey;
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
- tracker.noteStart(key1, true, bucketStartTimeNs + 1, conditionKey1);
+ tracker.noteStart(key1, true, bucketStartTimeNs + 1, ConditionKey());
// Another event starts in this bucket.
- tracker.noteStart(key2, true, bucketStartTimeNs + 20, conditionKey1);
+ tracker.noteStart(key2, true, bucketStartTimeNs + 20, ConditionKey());
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 40, &buckets);
tracker.noteStopAll(bucketStartTimeNs + bucketSizeNs + 40);
EXPECT_TRUE(tracker.mInfos.empty());
@@ -112,22 +108,20 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
- ConditionKey conditionKey1;
- conditionKey1[StringToId("condition")] = conditionKey;
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
// The event starts.
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, conditionKey1);
+ tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
// Starts again. Does not change anything.
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + bucketSizeNs + 1,
- conditionKey1);
+ ConditionKey());
// The event stops at early 4th bucket.
tracker.flushIfNeeded(bucketStartTimeNs + (3 * bucketSizeNs) + 20, &buckets);
@@ -144,19 +138,17 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
- ConditionKey conditionKey1;
- conditionKey1[StringToId("condition")] = conditionKey;
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
// 2 starts
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, conditionKey1);
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 10, conditionKey1);
+ tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
+ tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 10, ConditionKey());
// one stop
tracker.noteStop(DEFAULT_DIMENSION_KEY, bucketStartTimeNs + 20, false /*stop all*/);
@@ -196,7 +188,7 @@
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, true, {});
EXPECT_TRUE(tracker.mAnomalyTrackers.empty());
tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
@@ -218,31 +210,32 @@
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(32 * NS_PER_SEC);
alert.set_num_buckets(2);
- alert.set_refractory_period_secs(1);
+ const int32_t refPeriodSec = 1;
+ alert.set_refractory_period_secs(refPeriodSec);
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey conditionKey1;
- conditionKey1[StringToId("APP_BACKGROUND")] = conditionKey;
+
uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs,
- bucketSizeNs, {anomalyTracker});
+ bucketSizeNs, false, {anomalyTracker});
- tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
+ tracker.noteStart(key1, true, eventStartTimeNs, ConditionKey());
tracker.noteStop(key1, eventStartTimeNs + 10, false);
- EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs, -1);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
EXPECT_EQ(10LL, tracker.mDuration);
- tracker.noteStart(key2, true, eventStartTimeNs + 20, conditionKey1);
+ tracker.noteStart(key2, true, eventStartTimeNs + 20, ConditionKey());
tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, &buckets);
tracker.noteStop(key2, eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, false);
EXPECT_EQ((long long)(4 * NS_PER_SEC + 1LL), tracker.mDuration);
- EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs,
- (long long)(eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC));
+
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey),
+ (eventStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3 + refPeriodSec);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 36cdaae..6b8893e 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -47,9 +47,6 @@
TEST(OringDurationTrackerTest, TestDurationOverlap) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
-
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
uint64_t bucketStartTimeNs = 10000000000;
@@ -58,11 +55,11 @@
uint64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
- bucketStartTimeNs, bucketSizeNs, {});
+ bucketStartTimeNs, bucketSizeNs, false, {});
- tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
- tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, key1); // overlapping wl
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
@@ -76,9 +73,6 @@
TEST(OringDurationTrackerTest, TestDurationNested) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
-
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
uint64_t bucketStartTimeNs = 10000000000;
@@ -86,10 +80,10 @@
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
- tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
- tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, key1); // overlapping wl
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
tracker.noteStop(kEventKey1, eventStartTimeNs + 2000, false);
tracker.noteStop(kEventKey1, eventStartTimeNs + 2003, false);
@@ -103,9 +97,6 @@
TEST(OringDurationTrackerTest, TestStopAll) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
-
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
uint64_t bucketStartTimeNs = 10000000000;
@@ -113,10 +104,10 @@
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
- tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
- tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, key1); // overlapping wl
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
+ tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey()); // overlapping wl
tracker.noteStopAll(eventStartTimeNs + 2003);
@@ -129,9 +120,6 @@
TEST(OringDurationTrackerTest, TestCrossBucketBoundary) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
-
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
uint64_t bucketStartTimeNs = 10000000000;
@@ -140,12 +128,12 @@
uint64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, false, {});
- tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs, &buckets);
- tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2 * bucketSizeNs, key1);
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2 * bucketSizeNs, ConditionKey());
EXPECT_EQ((long long)(bucketStartTimeNs + 2 * bucketSizeNs), tracker.mLastStartTime);
EXPECT_EQ(2u, buckets[eventKey].size());
@@ -178,7 +166,7 @@
uint64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
- bucketStartTimeNs, bucketSizeNs, {});
+ bucketStartTimeNs, bucketSizeNs, true, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
@@ -211,7 +199,7 @@
uint64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
- bucketStartTimeNs, bucketSizeNs, {});
+ bucketStartTimeNs, bucketSizeNs, true, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
// condition to false; record duration 5n
@@ -243,7 +231,7 @@
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
- bucketSizeNs, {});
+ bucketSizeNs, true, {});
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1);
@@ -270,18 +258,17 @@
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
+
uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
- bucketSizeNs, {anomalyTracker});
+ bucketSizeNs, true, {anomalyTracker});
// Nothing in the past bucket.
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, key1);
+ tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)(alert.trigger_if_sum_gt() + eventStartTimeNs),
tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
@@ -289,7 +276,7 @@
EXPECT_EQ(0u, buckets[eventKey].size());
uint64_t event1StartTimeNs = eventStartTimeNs + 10;
- tracker.noteStart(kEventKey1, true, event1StartTimeNs, key1);
+ tracker.noteStart(kEventKey1, true, event1StartTimeNs, ConditionKey());
// No past buckets. The anomaly will happen in bucket #0.
EXPECT_EQ((long long)(event1StartTimeNs + alert.trigger_if_sum_gt() - 3),
tracker.predictAnomalyTimestampNs(*anomalyTracker, event1StartTimeNs));
@@ -308,7 +295,7 @@
// One past buckets. The anomaly will happen in bucket #1.
uint64_t event2StartTimeNs = eventStartTimeNs + bucketSizeNs + 15;
- tracker.noteStart(kEventKey1, true, event2StartTimeNs, key1);
+ tracker.noteStart(kEventKey1, true, event2StartTimeNs, ConditionKey());
EXPECT_EQ((long long)(event2StartTimeNs + alert.trigger_if_sum_gt() - bucket0Duration -
bucket1Duration),
tracker.predictAnomalyTimestampNs(*anomalyTracker, event2StartTimeNs));
@@ -317,48 +304,111 @@
// Only one past buckets is applicable. Bucket +0 should be trashed. The anomaly will happen in
// bucket #2.
uint64_t event3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs - 9 * NS_PER_SEC;
- tracker.noteStart(kEventKey1, true, event3StartTimeNs, key1);
+ tracker.noteStart(kEventKey1, true, event3StartTimeNs, ConditionKey());
EXPECT_EQ((long long)(event3StartTimeNs + alert.trigger_if_sum_gt() - bucket1Duration - 1LL),
tracker.predictAnomalyTimestampNs(*anomalyTracker, event3StartTimeNs));
}
-TEST(OringDurationTrackerTest, TestAnomalyDetection) {
+TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) {
Alert alert;
alert.set_id(101);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
alert.set_num_buckets(2);
- alert.set_refractory_period_secs(1);
+ const int32_t refPeriodSec = 45;
+ alert.set_refractory_period_secs(refPeriodSec);
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- ConditionKey key1;
- key1[StringToId("APP_BACKGROUND")] = kConditionKey1;
+
uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
- bucketStartTimeNs, bucketSizeNs, {anomalyTracker});
+ bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker});
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, key1);
- tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 10, false);
- EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs, -1);
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
+ tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
EXPECT_TRUE(tracker.mStarted.empty());
EXPECT_EQ(10LL, tracker.mDuration);
EXPECT_EQ(0u, tracker.mStarted.size());
- tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs + 20, key1);
+ tracker.noteStart(kEventKey1, true, eventStartTimeNs + 20, ConditionKey());
EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
EXPECT_EQ((long long)(51ULL * NS_PER_SEC),
(long long)(anomalyTracker->mAlarms.begin()->second->timestampSec * NS_PER_SEC));
+ // The alarm is set to fire at 51s, and when it does, an anomaly would be declared. However,
+ // because this is a unit test, the alarm won't actually fire at all. Since the alarm fails
+ // to fire in time, the anomaly is instead caught when noteStop is called, at around 71s.
tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 25, &buckets);
- tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 2 * bucketSizeNs + 25, false);
+ tracker.noteStop(kEventKey1, eventStartTimeNs + 2 * bucketSizeNs + 25, false);
EXPECT_EQ(anomalyTracker->getSumOverPastBuckets(eventKey), (long long)(bucketSizeNs));
- EXPECT_EQ((long long)(eventStartTimeNs + 2 * bucketSizeNs + 25),
- anomalyTracker->mLastAnomalyTimestampNs);
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey),
+ (eventStartTimeNs + 2 * bucketSizeNs + 25) / NS_PER_SEC + refPeriodSec);
+}
+
+TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) {
+ Alert alert;
+ alert.set_id(101);
+ alert.set_metric_id(1);
+ alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
+ alert.set_num_buckets(2);
+ const int32_t refPeriodSec = 45;
+ alert.set_refractory_period_secs(refPeriodSec);
+
+ unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ConditionKey conkey;
+ conkey[StringToId("APP_BACKGROUND")] = kConditionKey1;
+ uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
+ uint64_t bucketSizeNs = 30 * NS_PER_SEC;
+
+ sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
+ OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
+ bucketStartTimeNs, bucketSizeNs, false, {anomalyTracker});
+
+ tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1
+ EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+ sp<const AnomalyAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
+ EXPECT_EQ((long long)(55ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
+
+ tracker.noteStop(kEventKey1, 17 * NS_PER_SEC, false); // stop key1 (2 seconds later)
+ EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
+
+ tracker.noteStart(kEventKey1, true, 22 * NS_PER_SEC, conkey); // start key1 again
+ EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+ alarm = anomalyTracker->mAlarms.begin()->second;
+ EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
+
+ tracker.noteStart(kEventKey2, true, 32 * NS_PER_SEC, conkey); // start key2
+ EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+ alarm = anomalyTracker->mAlarms.begin()->second;
+ EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
+
+ tracker.noteStop(kEventKey1, 47 * NS_PER_SEC, false); // stop key1
+ EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+ alarm = anomalyTracker->mAlarms.begin()->second;
+ EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
+
+ // Now, at 60s, which is 38s after key1 started again, we have reached 40s of 'on' time.
+ std::unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> firedAlarms({alarm});
+ anomalyTracker->informAlarmsFired(62 * NS_PER_SEC, firedAlarms);
+ EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
+
+ tracker.noteStop(kEventKey2, 69 * NS_PER_SEC, false); // stop key2
+ EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 459da01..fff3dbf 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -249,7 +249,8 @@
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(130);
alert.set_num_buckets(2);
- alert.set_refractory_period_secs(3);
+ const int32_t refPeriodSec = 3;
+ alert.set_refractory_period_secs(refPeriodSec);
ValueMetric metric;
metric.set_id(metricId);
@@ -297,23 +298,28 @@
// Two events in bucket #0.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 30 <= 130.
+ // Value sum == 30 <= 130.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
// One event in bucket #2. No alarm as bucket #0 is trashed out.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 130 <= 130.
+ // Value sum == 130 <= 130.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
// Three events in bucket #3.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
// Anomaly at event 4 since Value sum == 131 > 130!
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
// Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
// Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
- EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event6->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
+ event6->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 939dc1f..e788235 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -292,6 +292,17 @@
uid, ProcessLifeCycleStateChanged::PROCESS_CRASHED, timestampNs);
}
+std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
+ int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
+ auto logEvent = std::make_unique<LogEvent>(
+ android::util::ISOLATED_UID_CHANGED, timestampNs);
+ logEvent->write(hostUid);
+ logEvent->write(isolatedUid);
+ logEvent->write(is_create);
+ logEvent->init();
+ return logEvent;
+}
+
sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
const ConfigKey& key) {
sp<UidMap> uidMap = new UidMap();
@@ -319,6 +330,54 @@
int64_t StringToId(const string& str) {
return static_cast<int64_t>(std::hash<std::string>()(str));
}
+
+void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid) {
+ EXPECT_EQ(value.field(), atomId);
+ EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
+ // Attribution field.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
+ // Uid only.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value_size(), 1);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).field(), 1);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).value_int(), uid);
+}
+
+void ValidateUidDimension(const DimensionsValue& value, int atomId, int uid) {
+ EXPECT_EQ(value.field(), atomId);
+ EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
+ // Attribution field.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
+ // Uid only.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value_size(), 1);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).field(), 1);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).value_int(), uid);
+}
+
+void ValidateAttributionUidAndTagDimension(
+ const DimensionsValue& value, int atomId, int uid, const std::string& tag) {
+ EXPECT_EQ(value.field(), atomId);
+ EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
+ // Attribution field.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
+ // Uid only.
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value_size(), 2);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).field(), 1);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(0).value_int(), uid);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(1).field(), 2);
+ EXPECT_EQ(value.value_tuple().dimensions_value(0)
+ .value_tuple().dimensions_value(1).value_str(), tag);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 5e19da0..1bbbd9a 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -111,6 +111,10 @@
const std::vector<AttributionNode>& attributions,
const string& wakelockName, uint64_t timestampNs);
+// Create log event for releasing wakelock.
+std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
+ int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
+
// Helper function to create an AttributionNode proto.
AttributionNode CreateAttribution(const int& uid, const string& tag);
@@ -123,6 +127,21 @@
int64_t StringToId(const string& str);
+void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
+void ValidateAttributionUidAndTagDimension(
+ const DimensionsValue& value, int atomId, int uid, const std::string& tag);
+
+template <typename T>
+void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) {
+ std::map<HashableDimensionKey, int> dimensionIndexMap;
+ for (int i = 0; i < metricData.data_size(); ++i) {
+ dimensionIndexMap.insert(std::make_pair(metricData.data(i).dimension(), i));
+ }
+ for (const auto& itr : dimensionIndexMap) {
+ *sortedMetricData->add_data() = metricData.data(itr.second);
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml
index f10b69d..d6f8047 100644
--- a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml
+++ b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml
@@ -49,7 +49,7 @@
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxLength="3"
+ android:maxLength="4"
android:text="@integer/replication_default"
android:textSize="30dp"/>
</LinearLayout>
@@ -64,15 +64,11 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/bucket_label" />
- <EditText
- android:id="@+id/bucket"
- android:inputType="number"
- android:layout_weight="1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:maxLength="3"
- android:text="@integer/bucket_default"
- android:textSize="30dp"/>
+ <Spinner
+ android:id="@+id/bucket_spinner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:prompt="@string/bucket_label"/>
</LinearLayout>
<LinearLayout
@@ -112,7 +108,7 @@
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxLength="2"
+ android:maxLength="4"
android:text="@integer/burst_default"
android:textSize="30dp"/>
</LinearLayout>
@@ -145,6 +141,7 @@
android:checked="false" />
<LinearLayout
+ android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
@@ -166,11 +163,6 @@
android:layout_height="wrap_content"
android:text="@string/event"
android:checked="true"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
<CheckBox
android:id="@+id/include_value"
android:layout_width="wrap_content"
diff --git a/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml b/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml
new file mode 100644
index 0000000..b03da06
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="30dp"
+ android:gravity="left"
+ android:padding="5dip"
+ />
diff --git a/cmds/statsd/tools/loadtest/res/raw/loadtest_config b/cmds/statsd/tools/loadtest/res/raw/loadtest_config
index fbce0e8..2422190 100755
--- a/cmds/statsd/tools/loadtest/res/raw/loadtest_config
+++ b/cmds/statsd/tools/loadtest/res/raw/loadtest_config
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/values/integers.xml b/cmds/statsd/tools/loadtest/res/values/integers.xml
index 76b5692..c2407d3 100644
--- a/cmds/statsd/tools/loadtest/res/values/integers.xml
+++ b/cmds/statsd/tools/loadtest/res/values/integers.xml
@@ -17,7 +17,6 @@
*/
-->
<resources>
- <integer name="bucket_default">10</integer>
<integer name="burst_default">1</integer>
<integer name="period_default">2</integer>
<integer name="replication_default">1</integer>
diff --git a/cmds/statsd/tools/loadtest/res/values/strings.xml b/cmds/statsd/tools/loadtest/res/values/strings.xml
index d0f77c6..e8ae3f8 100644
--- a/cmds/statsd/tools/loadtest/res/values/strings.xml
+++ b/cmds/statsd/tools/loadtest/res/values/strings.xml
@@ -20,6 +20,7 @@
<string name="app_name">Statsd Loadtest</string>
<string name="bucket_label">bucket size (mins): </string>
<string name="burst_label">burst: </string>
+ <string name="bucket_default">FIVE_MINUTES</string>
<string name="placebo">placebo</string>
<string name="period_label">logging period (secs): </string>
<string name="replication_label">metric replication: </string>
diff --git a/cmds/statsd/tools/loadtest/run_loadtest.sh b/cmds/statsd/tools/loadtest/run_loadtest.sh
new file mode 100755
index 0000000..3c93a06
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/run_loadtest.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+# Script that measures statsd's PSS under an increasing number of metrics.
+
+# Globals.
+pss=""
+pid=""
+
+# Starts the loadtest.
+start_loadtest() {
+ echo "Starting loadtest"
+ adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "start"
+}
+
+# Stops the loadtest.
+stop_loadtest() {
+ echo "Stopping loadtest"
+ adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "stop"
+}
+
+# Sets the metrics replication.
+# Arguments:
+# $1: The replication factor.
+set_replication() {
+ adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "set_replication" --ei "replication" "${1}"
+ echo "Replication set to ${1}"
+}
+
+# Reads statsd's pid and PSS.
+update_pid_and_pss() {
+ # Command that reads the PSS for statsd. This also gives us its pid.
+ get_mem=$(adb shell dumpsys meminfo |grep statsd)
+ # Looks for statsd's pid.
+ regex="([0-9,]+)K: statsd \(pid ([0-9]+)\).*"
+ if [[ $get_mem =~ $regex ]]; then
+ pss=$(echo "${BASH_REMATCH[1]}" | tr -d , | sed 's/\.//g')
+ pid=$(echo "${BASH_REMATCH[2]}")
+ else
+ echo $cmd doesnt match $regex
+ fi
+}
+
+# Kills statsd.
+# Assumes the pid has been set.
+kill_statsd() {
+ echo "Killing statsd (pid ${pid})"
+ adb shell kill -9 "${pid}"
+}
+
+# Main loop.
+main() {
+ start_time=$(date +%s)
+ values=()
+ stop_loadtest
+
+ echo ""
+ echo "********************* NEW LOADTEST ************************"
+ update_pid_and_pss
+ for replication in 1 2 4 8 16 32 64 128 256 512 1024 2048 4096
+ do
+ echo "**** Starting test at replication ${replication} ****"
+
+ # (1) Restart statsd. This will ensure its state is empty.
+ kill_statsd
+ sleep 3 # wait a bit for it to restart
+ update_pid_and_pss
+ echo "Before the test, statsd's PSS is ${pss}"
+
+ # (2) Set the replication.
+ set_replication "${replication}"
+ sleep 1 # wait a bit
+
+ # (3) Start the loadtest.
+ start_loadtest
+
+ # (4) Wait several seconds, then read the PSS.
+ sleep 100 && update_pid_and_pss
+ echo "During the test, statsd's PSS is ${pss}"
+ values+=(${pss})
+
+ echo "Values: ${values[@]}"
+
+ # (5) Stop loadtest.
+ stop_loadtest
+ sleep 2
+
+ echo ""
+ done
+
+ end_time=$(date +%s)
+ echo "Completed loadtest in $((${end_time} - ${start_time})) seconds."
+
+ values_as_str=$(IFS=$'\n'; echo "${values[*]}")
+ echo "The PSS values are:"
+ echo "${values_as_str}"
+ echo ""
+}
+
+main
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java
index 709b28b29..bab0c1e 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java
@@ -28,8 +28,10 @@
private static final String DUMP_FILENAME = TAG + "_dump.tmp";
public BatteryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs,
- int burst) {
- super(placebo, replication, bucket, periodSecs, burst);
+ int burst, boolean includeCountMetric, boolean includeDurationMetric,
+ boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) {
+ super(placebo, replication, bucket, periodSecs, burst, includeCountMetric,
+ includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric);
}
@Override
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 b492ea9..843b1e5 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
@@ -42,6 +42,16 @@
* Creates StatsdConfig protos for loadtesting.
*/
public class ConfigFactory {
+ public static class ConfigMetadata {
+ public final byte[] bytes;
+ public final int numMetrics;
+
+ public ConfigMetadata(byte[] bytes, int numMetrics) {
+ this.bytes = bytes;
+ this.numMetrics = numMetrics;
+ }
+ }
+
public static final long CONFIG_ID = 123456789;
private static final String TAG = "loadtest.ConfigFactory";
@@ -81,11 +91,11 @@
* ones
* @param bucketMillis The bucket size, in milliseconds, for aggregate metrics
* @param placebo If true, only return an empty config
- * @return The serialized config
+ * @return The serialized config and the number of metrics.
*/
- public byte[] getConfig(int replication, TimeUnit bucket, boolean placebo, boolean includeCount,
- boolean includeDuration, boolean includeEvent, boolean includeValue,
- boolean includeGauge) {
+ public ConfigMetadata getConfig(int replication, TimeUnit bucket, boolean placebo,
+ boolean includeCount, boolean includeDuration, boolean includeEvent,
+ boolean includeValue, boolean includeGauge) {
StatsdConfig.Builder config = StatsdConfig.newBuilder()
.setId(CONFIG_ID);
if (placebo) {
@@ -137,7 +147,7 @@
Log.d(TAG, "Loadtest config is : " + config.build());
Log.d(TAG, "Generated config has " + numMetrics + " metrics");
- return config.build().toByteArray();
+ return new ConfigMetadata(config.build().toByteArray(), numMetrics);
}
/**
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
index 19087d8..862ebe14 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
@@ -22,18 +22,28 @@
import java.util.List;
public class DisplayProtoUtils {
+ private static final int MAX_NUM_METRICS_TO_DISPLAY = 10;
+
public static void displayLogReport(StringBuilder sb, StatsLog.ConfigMetricsReportList reports) {
- sb.append("ConfigKey: ");
+ sb.append("******************** Report ********************\n");
if (reports.hasConfigKey()) {
+ sb.append("ConfigKey: ");
com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey key = reports.getConfigKey();
sb.append("\tuid: ").append(key.getUid()).append(" id: ").append(key.getId())
.append("\n");
}
+ int numMetrics = 0;
for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) {
sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n");
for (StatsLog.StatsLogReport log : report.getMetricsList()) {
- sb.append("\n\n");
+ numMetrics++;
+ if (numMetrics > MAX_NUM_METRICS_TO_DISPLAY) {
+ sb.append("... output truncated\n");
+ sb.append("************************************************");
+ return;
+ }
+ sb.append("\n");
sb.append("metric id: ").append(log.getMetricId()).append("\n");
sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n");
sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n");
@@ -65,6 +75,7 @@
}
}
}
+ sb.append("************************************************");
}
public static String getDateStr(long nanoSec) {
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
index 056ac0c..26c1c72 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
@@ -39,16 +39,22 @@
import android.view.inputmethod.InputMethodManager;
import android.view.MotionEvent;
import android.view.View.OnFocusChangeListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
+import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.android.os.StatsLog.ConfigMetricsReport;
import com.android.os.StatsLog.ConfigMetricsReportList;
import com.android.os.StatsLog.StatsdStatsReport;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Runs a load test for statsd.
@@ -68,14 +74,18 @@
* <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period).
* </ul>
*/
-public class LoadtestActivity extends Activity {
+public class LoadtestActivity extends Activity implements AdapterView.OnItemSelectedListener {
- private static final String TAG = "StatsdLoadtest";
+ private static final String TAG = "loadtest.LoadtestActivity";
public static final String TYPE = "type";
private static final String PUSH_ALARM = "push_alarm";
public static final String PERF_ALARM = "perf_alarm";
+ private static final String SET_REPLICATION = "set_replication";
+ private static final String REPLICATION = "replication";
private static final String START = "start";
private static final String STOP = "stop";
+ private static final Map<String, TimeUnit> TIME_UNIT_MAP = initializeTimeUnitMap();
+ private static final List<String> TIME_UNIT_LABELS = initializeTimeUnitLabels();
public final static class PusherAlarmReceiver extends BroadcastReceiver {
@Override
@@ -95,6 +105,35 @@
}
}
+ private static Map<String, TimeUnit> initializeTimeUnitMap() {
+ Map<String, TimeUnit> labels = new HashMap();
+ labels.put("1m", TimeUnit.ONE_MINUTE);
+ labels.put("5m", TimeUnit.FIVE_MINUTES);
+ labels.put("10m", TimeUnit.TEN_MINUTES);
+ labels.put("30m", TimeUnit.THIRTY_MINUTES);
+ labels.put("1h", TimeUnit.ONE_HOUR);
+ labels.put("3h", TimeUnit.THREE_HOURS);
+ labels.put("6h", TimeUnit.SIX_HOURS);
+ labels.put("12h", TimeUnit.TWELVE_HOURS);
+ labels.put("1d", TimeUnit.ONE_DAY);
+ labels.put("1s", TimeUnit.CTS);
+ return labels;
+ }
+ private static List<String> initializeTimeUnitLabels() {
+ List<String> labels = new ArrayList();
+ labels.add("1s");
+ labels.add("1m");
+ labels.add("5m");
+ labels.add("10m");
+ labels.add("30m");
+ labels.add("1h");
+ labels.add("3h");
+ labels.add("6h");
+ labels.add("12h");
+ labels.add("1d");
+ return labels;
+ }
+
private AlarmManager mAlarmMgr;
/** Used to periodically log atoms to logd. */
@@ -105,7 +144,7 @@
private Button mStartStop;
private EditText mReplicationText;
- private EditText mBucketText;
+ private Spinner mBucketSpinner;
private EditText mPeriodText;
private EditText mBurstText;
private EditText mDurationText;
@@ -187,11 +226,14 @@
/** For intra-minute periods. */
private final Handler mHandler = new Handler();
+ /** Number of metrics in the current config. */
+ private int mNumMetrics;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Log.d(TAG, "Starting loadtest");
+ Log.d(TAG, "Starting loadtest Activity");
setContentView(R.layout.activity_loadtest);
mReportText = (TextView) findViewById(R.id.report_text);
@@ -249,6 +291,11 @@
case PUSH_ALARM:
onAlarm();
break;
+ case SET_REPLICATION:
+ if (intent.hasExtra(REPLICATION)) {
+ setReplication(intent.getIntExtra(REPLICATION, 0));
+ }
+ break;
case START:
startLoadtest();
break;
@@ -300,6 +347,10 @@
ConfigMetricsReportList reports = null;
try {
reports = ConfigMetricsReportList.parseFrom(data);
+ Log.d(TAG, "Num reports: " + reports.getReportsCount());
+ StringBuilder sb = new StringBuilder();
+ DisplayProtoUtils.displayLogReport(sb, reports);
+ Log.d(TAG, sb.toString());
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
Log.d(TAG, "Invalid data");
}
@@ -311,6 +362,18 @@
return null;
}
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ String item = parent.getItemAtPosition(position).toString();
+
+ mBucket = TIME_UNIT_MAP.get(item);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Another interface callback
+ }
+
private void onPerfAlarm() {
if (mPerfData != null) {
mPerfData.onAlarm(this);
@@ -318,7 +381,9 @@
// Piggy-back on that alarm to show the elapsed time.
long elapsedTimeMins = (long) Math.floor(
(SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
- mReportText.setText("Loadtest in progress. Elapsed time = " + elapsedTimeMins + " min(s)");
+ mReportText.setText("Loadtest in progress.\n"
+ + "num metrics =" + mNumMetrics
+ + "\nElapsed time = " + elapsedTimeMins + " min(s)");
}
private void onAlarm() {
@@ -357,9 +422,6 @@
// Prepare to push a sequence of atoms to logd.
mPusher = new SequencePusher(mBurst, mPlacebo);
- // Force a data flush by requesting data.
- getData();
-
// Create a config and push it to statsd.
if (!setConfig(mFactory.getConfig(mReplication, mBucket, mPlacebo,
mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric,
@@ -378,10 +440,12 @@
scheduleNext();
// Start tracking performance.
- mPerfData = new PerfData(this, mPlacebo, mReplication, mBucket, mPeriodSecs, mBurst);
+ mPerfData = new PerfData(this, mPlacebo, mReplication, mBucket, mPeriodSecs, mBurst,
+ mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, mIncludeValueMetric,
+ mIncludeGaugeMetric);
mPerfData.startRecording(this);
- mReportText.setText("Loadtest in progress.");
+ mReportText.setText("Loadtest in progress.\nnum metrics =" + mNumMetrics);
mStartedTimeMillis = SystemClock.elapsedRealtime();
updateStarted(true);
@@ -408,6 +472,9 @@
mPerfData = null;
}
+ // Obtain the latest data and display it.
+ getData();
+
long elapsedTimeMins = (long) Math.floor(
(SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000);
mReportText.setText("Loadtest ended. Elapsed time = " + elapsedTimeMins + " min(s)");
@@ -427,9 +494,16 @@
mBurstText.setEnabled(!mPlacebo && !mStarted);
mReplicationText.setEnabled(!mPlacebo && !mStarted);
mPeriodText.setEnabled(!mStarted);
- mBucketText.setEnabled(!mPlacebo && !mStarted);
+ mBucketSpinner.setEnabled(!mPlacebo && !mStarted);
mDurationText.setEnabled(!mStarted);
mPlaceboCheckBox.setEnabled(!mStarted);
+
+ boolean enabled = !mStarted && !mPlaceboCheckBox.isChecked();
+ mCountMetricCheckBox.setEnabled(enabled);
+ mDurationMetricCheckBox.setEnabled(enabled);
+ mEventMetricCheckBox.setEnabled(enabled);
+ mValueMetricCheckBox.setEnabled(enabled);
+ mGaugeMetricCheckBox.setEnabled(enabled);
}
private boolean statsdRunning() {
@@ -463,10 +537,11 @@
}
}
- private boolean setConfig(byte[] config) {
+ private boolean setConfig(ConfigFactory.ConfigMetadata configData) {
if (mStatsManager != null) {
if (mStatsManager.addConfiguration(ConfigFactory.CONFIG_ID,
- config, getPackageName(), LoadtestActivity.this.getClass().getName())) {
+ configData.bytes, getPackageName(), LoadtestActivity.this.getClass().getName())) {
+ mNumMetrics = configData.numMetrics;
Log.d(TAG, "Config pushed to statsd");
return true;
} else {
@@ -477,17 +552,16 @@
}
private synchronized void setReplication(int replication) {
- mReplication = replication;
+ if (mStarted) {
+ return;
+ }
+ mReplicationText.setText("" + replication);
}
private synchronized void setPeriodSecs(long periodSecs) {
mPeriodSecs = periodSecs;
}
- private synchronized void setBucket(TimeUnit bucket) {
- mBucket = bucket;
- }
-
private synchronized void setBurst(int burst) {
mBurst = burst;
}
@@ -496,12 +570,9 @@
mDurationMins = durationMins;
}
- private synchronized void setPlacebo(boolean placebo) {
- mPlacebo = placebo;
- updateControlsEnabled();
- }
private void handleFocus(EditText editText) {
+ /*
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
@@ -510,12 +581,13 @@
}
}
});
+ */
}
private void initBurst() {
mBurst = getResources().getInteger(R.integer.burst_default);
mBurstText = (EditText) findViewById(R.id.burst);
- mBurstText.addTextChangedListener(new NumericalWatcher(mBurstText, 0, 50) {
+ mBurstText.addTextChangedListener(new NumericalWatcher(mBurstText, 0, 1000) {
@Override
public void onNewValue(int newValue) {
setBurst(newValue);
@@ -527,25 +599,31 @@
private void initReplication() {
mReplication = getResources().getInteger(R.integer.replication_default);
mReplicationText = (EditText) findViewById(R.id.replication);
- mReplicationText.addTextChangedListener(new NumericalWatcher(mReplicationText, 1, 100) {
+ mReplicationText.addTextChangedListener(new NumericalWatcher(mReplicationText, 1, 4096) {
@Override
public void onNewValue(int newValue) {
- setReplication(newValue);
+ mReplication = newValue;
}
});
handleFocus(mReplicationText);
}
private void initBucket() {
- mBucket = TimeUnit.valueOf(getResources().getInteger(R.integer.bucket_default));
- mBucketText = (EditText) findViewById(R.id.bucket);
- mBucketText.addTextChangedListener(new NumericalWatcher(mBucketText, 1, 9) {
- @Override
- public void onNewValue(int newValue) {
- setBucket(TimeUnit.valueOf(newValue));
+ String defaultValue = getResources().getString(R.string.bucket_default);
+ mBucket = TimeUnit.valueOf(defaultValue);
+ mBucketSpinner = (Spinner) findViewById(R.id.bucket_spinner);
+
+ ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(
+ this, R.layout.spinner_item, TIME_UNIT_LABELS);
+
+ mBucketSpinner.setAdapter(dataAdapter);
+ mBucketSpinner.setOnItemSelectedListener(this);
+
+ for (String label : TIME_UNIT_MAP.keySet()) {
+ if (defaultValue.equals(TIME_UNIT_MAP.get(label).toString())) {
+ mBucketSpinner.setSelection(dataAdapter.getPosition(label));
}
- });
- handleFocus(mBucketText);
+ }
}
private void initPeriod() {
@@ -578,7 +656,8 @@
mPlaceboCheckBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- setPlacebo(((CheckBox) view).isChecked());
+ mPlacebo = mPlaceboCheckBox.isChecked();
+ updateControlsEnabled();
}
});
}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java
index 66bcbff..af7bd4d 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java
@@ -28,8 +28,10 @@
private StringBuilder mSb;
public MemoryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs,
- int burst) {
- super(placebo, replication, bucket, periodSecs, burst);
+ int burst, boolean includeCountMetric, boolean includeDurationMetric,
+ boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) {
+ super(placebo, replication, bucket, periodSecs, burst, includeCountMetric,
+ includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric);
}
@Override
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java
index 4b4e368..7a01ade 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java
@@ -54,15 +54,24 @@
private final Set<PerfDataRecorder> mRecorders;
public PerfData(LoadtestActivity loadtestActivity, boolean placebo, int replication,
- TimeUnit bucket, long periodSecs, int burst) {
- super(placebo, replication, bucket, periodSecs, burst);
+ TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric,
+ boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric,
+ boolean includeGaugeMetric) {
+ super(placebo, replication, bucket, periodSecs, burst, includeCountMetric,
+ includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric);
mRecorders = new HashSet();
- mRecorders.add(new BatteryDataRecorder(placebo, replication, bucket, periodSecs, burst));
- mRecorders.add(new MemoryDataRecorder(placebo, replication, bucket, periodSecs, burst));
+ mRecorders.add(new BatteryDataRecorder(placebo, replication, bucket, periodSecs, burst,
+ includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric,
+ includeGaugeMetric));
+ mRecorders.add(new MemoryDataRecorder(placebo, replication, bucket, periodSecs, burst,
+ includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric,
+ includeGaugeMetric));
mRecorders.add(new StatsdStatsRecorder(loadtestActivity, placebo, replication, bucket,
- periodSecs, burst));
+ periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric,
+ includeValueMetric, includeGaugeMetric));
mRecorders.add(new ValidationRecorder(loadtestActivity, placebo, replication, bucket,
- periodSecs, burst));
+ periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric,
+ includeValueMetric, includeGaugeMetric));
mAlarmMgr = (AlarmManager) loadtestActivity.getSystemService(Context.ALARM_SERVICE);
}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java
index fd182ad..8613ac1 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java
@@ -40,9 +40,12 @@
protected final String mColumnSuffix;
protected PerfDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs,
- int burst) {
+ int burst, boolean includeCountMetric, boolean includeDurationMetric,
+ boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) {
mTimeAsString = new SimpleDateFormat("YYYY_MM_dd_HH_mm_ss").format(new Date());
- mColumnSuffix = getColumnSuffix(placebo, replication, bucket, periodSecs, burst);
+ mColumnSuffix = getColumnSuffix(placebo, replication, bucket, periodSecs, burst,
+ includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric,
+ includeGaugeMetric);
}
/** Starts recording performance data. */
@@ -122,14 +125,35 @@
/** Gets the suffix to use in the column name for perf data. */
private String getColumnSuffix(boolean placebo, int replication, TimeUnit bucket,
- long periodSecs, int burst) {
+ long periodSecs, int burst, boolean includeCountMetric, boolean includeDurationMetric,
+ boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) {
if (placebo) {
return "_placebo_p=" + periodSecs;
}
- return "_r=" + replication + "_bkt=" + bucket + "_p=" + periodSecs + "_bst=" + burst;
+ StringBuilder sb = new StringBuilder()
+ .append("_r=" + replication)
+ .append("_bkt=" + bucket)
+ .append("_p=" + periodSecs)
+ .append("_bst=" + burst)
+ .append("_m=");
+ if (includeCountMetric) {
+ sb.append("c");
+ }
+ if (includeEventMetric) {
+ sb.append("e");
+ }
+ if (includeDurationMetric) {
+ sb.append("d");
+ }
+ if (includeGaugeMetric) {
+ sb.append("g");
+ }
+ if (includeValueMetric) {
+ sb.append("v");
+ }
+ return sb.toString();
}
-
private File getStorageDir() {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "loadtest/" + mTimeAsString);
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java
index 1e30fdf..e63150f 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java
@@ -28,8 +28,11 @@
private final LoadtestActivity mLoadtestActivity;
public StatsdStatsRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication,
- TimeUnit bucket, long periodSecs, int burst) {
- super(placebo, replication, bucket, periodSecs, burst);
+ TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric,
+ boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric,
+ boolean includeGaugeMetric) {
+ super(placebo, replication, bucket, periodSecs, burst, includeCountMetric,
+ includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric);
mLoadtestActivity = loadtestActivity;
}
@@ -56,7 +59,7 @@
.append(configStats.getConditionCount() + "\n")
.append("matcher_count,")
.append(configStats.getMatcherCount() + "\n");
- writeData(context, "statsdstats_", "", sb);
+ writeData(context, "statsdstats_", "stat,value", sb);
}
}
}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java
index 5d26be3..d9f0ca9 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java
@@ -34,8 +34,11 @@
private final LoadtestActivity mLoadtestActivity;
public ValidationRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication,
- TimeUnit bucket, long periodSecs, int burst) {
- super(placebo, replication, bucket, periodSecs, burst);
+ TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric,
+ boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric,
+ boolean includeGaugeMetric) {
+ super(placebo, replication, bucket, periodSecs, burst, includeCountMetric,
+ includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric);
mLoadtestActivity = loadtestActivity;
}
@@ -55,6 +58,9 @@
}
private void validateData() {
+ // The code below is commented out because it calls getData, which has the side-effect
+ // of clearing statsd's data buffer.
+ /*
List<ConfigMetricsReport> reports = mLoadtestActivity.getData();
if (reports != null) {
Log.d(TAG, "GOT DATA");
@@ -66,6 +72,7 @@
}
}
}
+ */
}
private void validateEventBatteryLevelChanges(StatsLogReport logReport) {
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index adbe9d0..34f6d7d 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -38,6 +39,9 @@
+ "\n"
+ "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n"
+ " Set the current usb function and optionally the data lock state.\n\n"
+ + " svc usb setScreenUnlockedFunctions [function]\n"
+ + " Sets the functions which, if the device was charging,"
+ + " become current on screen unlock.\n"
+ " svc usb getFunction\n"
+ " Gets the list of currently enabled functions\n";
}
@@ -62,6 +66,16 @@
} else if ("getFunction".equals(args[1])) {
System.err.println(SystemProperties.get("sys.usb.config"));
return;
+ } else if ("setScreenUnlockedFunctions".equals(args[1])) {
+ IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
+ Context.USB_SERVICE));
+ try {
+ usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] :
+ UsbManager.USB_FUNCTION_NONE));
+ } catch (RemoteException e) {
+ System.err.println("Error communicating with UsbManager: " + e);
+ }
+ return;
}
}
System.err.println(longHelp());
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index 55028eb..e96ff01 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -39,6 +39,6 @@
* @hide
*/
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.RUNTIME)
public @interface SystemApi {
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 847f91b..4554584 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -485,11 +485,11 @@
* all activities that are visible to the user. */
public static final int PROCESS_STATE_TOP = 2;
- /** @hide Process is hosting a foreground service due to a system binding. */
- public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
-
/** @hide Process is hosting a foreground service. */
- public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
+ public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
+
+ /** @hide Process is hosting a foreground service due to a system binding. */
+ public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 4;
/** @hide Process is important to the user, and something they are aware of. */
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 5;
@@ -3086,11 +3086,11 @@
} else if (importance >= IMPORTANCE_VISIBLE) {
return PROCESS_STATE_IMPORTANT_FOREGROUND;
} else if (importance >= IMPORTANCE_TOP_SLEEPING_PRE_28) {
- return PROCESS_STATE_FOREGROUND_SERVICE;
+ return PROCESS_STATE_IMPORTANT_FOREGROUND;
} else if (importance >= IMPORTANCE_FOREGROUND_SERVICE) {
return PROCESS_STATE_FOREGROUND_SERVICE;
} else {
- return PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ return PROCESS_STATE_TOP;
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d32f57a..57f9f67 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1601,6 +1601,7 @@
}
/** @hide */
+ @TestApi
public void setMode(int code, int uid, String packageName, int mode) {
try {
mService.setMode(code, uid, packageName, mode);
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index d0f84c8..857a30e 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.trust.ITrustManager;
import android.content.Context;
@@ -172,6 +173,7 @@
*
* @hide
*/
+ @SystemApi
public Intent createConfirmFactoryResetCredentialIntent(
CharSequence title, CharSequence description, CharSequence alternateButtonLabel) {
if (!LockPatternUtils.frpCredentialEnabled(mContext)) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 85c3be8..a383604 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1022,10 +1022,18 @@
/**
* {@link #extras} key: A String array containing the people that this notification relates to,
* each of which was supplied to {@link Builder#addPerson(String)}.
+ *
+ * @deprecated the actual objects are now in {@link #EXTRA_PEOPLE_LIST}
*/
public static final String EXTRA_PEOPLE = "android.people";
/**
+ * {@link #extras} key: An arrayList of {@link Person} objects containing the people that
+ * this notification relates to.
+ */
+ public static final String EXTRA_PEOPLE_LIST = "android.people.list";
+
+ /**
* Allow certain system-generated notifications to appear before the device is provisioned.
* Only available to notifications coming from the android package.
* @hide
@@ -1063,10 +1071,20 @@
* direct replies
* {@link android.app.Notification.MessagingStyle} notification. This extra is a
* {@link CharSequence}
+ *
+ * @deprecated use {@link #EXTRA_MESSAGING_PERSON}
*/
public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
/**
+ * {@link #extras} key: the person to be displayed for all messages sent by the user including
+ * direct replies
+ * {@link android.app.Notification.MessagingStyle} notification. This extra is a
+ * {@link Person}
+ */
+ public static final String EXTRA_MESSAGING_PERSON = "android.messagingUser";
+
+ /**
* {@link #extras} key: a {@link CharSequence} to be displayed as the title to a conversation
* represented by a {@link android.app.Notification.MessagingStyle}
*/
@@ -2819,7 +2837,7 @@
private Bundle mUserExtras = new Bundle();
private Style mStyle;
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
- private ArrayList<String> mPersonList = new ArrayList<String>();
+ private ArrayList<Person> mPersonList = new ArrayList<>();
private NotificationColorUtil mColorUtil;
private boolean mIsLegacy;
private boolean mIsLegacyInitialized;
@@ -2910,8 +2928,9 @@
Collections.addAll(mActions, mN.actions);
}
- if (mN.extras.containsKey(EXTRA_PEOPLE)) {
- Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
+ if (mN.extras.containsKey(EXTRA_PEOPLE_LIST)) {
+ ArrayList<Person> people = mN.extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
+ mPersonList.addAll(people);
}
if (mN.getSmallIcon() == null && mN.icon != 0) {
@@ -3621,13 +3640,41 @@
* URIs. The path part of these URIs must exist in the contacts database, in the
* appropriate column, or the reference will be discarded as invalid. Telephone schema
* URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
+ * It is also possible to provide a URI with the schema {@code name:} in order to uniquely
+ * identify a person without an entry in the contacts database.
* </P>
*
* @param uri A URI for the person.
* @see Notification#EXTRA_PEOPLE
+ * @deprecated use {@link #addPerson(Person)}
*/
public Builder addPerson(String uri) {
- mPersonList.add(uri);
+ addPerson(new Person().setUri(uri));
+ return this;
+ }
+
+ /**
+ * Add a person that is relevant to this notification.
+ *
+ * <P>
+ * Depending on user preferences, this annotation may allow the notification to pass
+ * through interruption filters, if this notification is of category {@link #CATEGORY_CALL}
+ * or {@link #CATEGORY_MESSAGE}. The addition of people may also cause this notification to
+ * appear more prominently in the user interface.
+ * </P>
+ *
+ * <P>
+ * A person should usually contain a uri in order to benefit from the ranking boost.
+ * However, even if no uri is provided, it's beneficial to provide other people in the
+ * notification, such that listeners and voice only devices can announce and handle them
+ * properly.
+ * </P>
+ *
+ * @param person the person to add.
+ * @see Notification#EXTRA_PEOPLE_LIST
+ */
+ public Builder addPerson(Person person) {
+ mPersonList.add(person);
return this;
}
@@ -3934,7 +3981,10 @@
contentView.setViewVisibility(R.id.chronometer, View.GONE);
contentView.setViewVisibility(R.id.header_text, View.GONE);
contentView.setTextViewText(R.id.header_text, null);
+ contentView.setViewVisibility(R.id.header_text_secondary, View.GONE);
+ contentView.setTextViewText(R.id.header_text_secondary, null);
contentView.setViewVisibility(R.id.header_text_divider, View.GONE);
+ contentView.setViewVisibility(R.id.header_text_secondary_divider, View.GONE);
contentView.setViewVisibility(R.id.time_divider, View.GONE);
contentView.setViewVisibility(R.id.time, View.GONE);
contentView.setImageViewIcon(R.id.profile_badge, null);
@@ -3965,7 +4015,7 @@
final Bundle ex = mN.extras;
updateBackgroundColor(contentView);
- bindNotificationHeader(contentView, p.ambient);
+ bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
bindLargeIcon(contentView, p.hideLargeIcon, p.alwaysShowReply);
boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
if (p.title != null) {
@@ -4248,12 +4298,14 @@
return null;
}
- private void bindNotificationHeader(RemoteViews contentView, boolean ambient) {
+ private void bindNotificationHeader(RemoteViews contentView, boolean ambient,
+ CharSequence secondaryHeaderText) {
bindSmallIcon(contentView, ambient);
bindHeaderAppName(contentView, ambient);
if (!ambient) {
// Ambient view does not have these
bindHeaderText(contentView);
+ bindHeaderTextSecondary(contentView, secondaryHeaderText);
bindHeaderChronometerAndTime(contentView);
bindProfileBadge(contentView);
}
@@ -4322,6 +4374,17 @@
}
}
+ private void bindHeaderTextSecondary(RemoteViews contentView, CharSequence secondaryText) {
+ if (!TextUtils.isEmpty(secondaryText)) {
+ contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
+ processLegacyText(secondaryText)));
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary);
+ contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
+ contentView.setViewVisibility(R.id.header_text_secondary_divider, View.VISIBLE);
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary_divider);
+ }
+ }
+
/**
* @hide
*/
@@ -4555,7 +4618,7 @@
ambient ? R.layout.notification_template_ambient_header
: R.layout.notification_template_header);
resetNotificationHeader(header);
- bindNotificationHeader(header, ambient);
+ bindNotificationHeader(header, ambient, null);
if (colorized != null) {
mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
} else {
@@ -4968,8 +5031,7 @@
mActions.toArray(mN.actions);
}
if (!mPersonList.isEmpty()) {
- mN.extras.putStringArray(EXTRA_PEOPLE,
- mPersonList.toArray(new String[mPersonList.size()]));
+ mN.extras.putParcelableArrayList(EXTRA_PEOPLE_LIST, mPersonList);
}
if (mN.bigContentView != null || mN.contentView != null
|| mN.headsUpContentView != null) {
@@ -5965,7 +6027,7 @@
*/
public static final int MAXIMUM_RETAINED_MESSAGES = 25;
- CharSequence mUserDisplayName;
+ @NonNull Person mUser;
@Nullable CharSequence mConversationTitle;
List<Message> mMessages = new ArrayList<>();
List<Message> mHistoricMessages = new ArrayList<>();
@@ -5979,23 +6041,54 @@
* user before the posting app reposts the notification with those messages after they've
* been actually sent and in previous messages sent by the user added in
* {@link #addMessage(Notification.MessagingStyle.Message)}
+ *
+ * @deprecated use {@code MessagingStyle(Person)}
*/
public MessagingStyle(@NonNull CharSequence userDisplayName) {
- mUserDisplayName = userDisplayName;
+ this(new Person().setName(userDisplayName));
+ }
+
+ /**
+ * @param user Required - The person displayed for any messages that are sent by the
+ * user. Any messages added with {@link #addMessage(Notification.MessagingStyle.Message)}
+ * who don't have a Person associated with it will be displayed as if they were sent
+ * by this user. The user also needs to have a valid name associated with it.
+ */
+ public MessagingStyle(@NonNull Person user) {
+ mUser = user;
+ if (user == null || user.getName() == null) {
+ throw new RuntimeException("user must be valid and have a name");
+ }
+ }
+
+ /**
+ * @return the user to be displayed for any replies sent by the user
+ */
+ public Person getUser() {
+ return mUser;
}
/**
* Returns the name to be displayed for any replies sent by the user
+ *
+ * @deprecated use {@link #getUser()} instead
*/
public CharSequence getUserDisplayName() {
- return mUserDisplayName;
+ return mUser.getName();
}
/**
* Sets the title to be displayed on this conversation. May be set to {@code null}.
*
- * @param conversationTitle A name for the conversation, or {@code null}
- * @return this object for method chaining.
+ * <p>This API's behavior was changed in SDK version {@link Build.VERSION_CODES#P}. If your
+ * application's target version is less than {@link Build.VERSION_CODES#P}, setting a
+ * conversation title to a non-null value will make {@link #isGroupConversation()} return
+ * {@code true} and passing {@code null} will make it return {@code false}. In
+ * {@link Build.VERSION_CODES#P} and beyond, use {@link #setGroupConversation(boolean)}
+ * to set group conversation status.
+ *
+ * @param conversationTitle Title displayed for this conversation
+ * @return this object for method chaining
*/
public MessagingStyle setConversationTitle(@Nullable CharSequence conversationTitle) {
mConversationTitle = conversationTitle;
@@ -6024,8 +6117,28 @@
* @see Message#Message(CharSequence, long, CharSequence)
*
* @return this object for method chaining
+ *
+ * @deprecated use {@link #addMessage(CharSequence, long, Person)}
*/
public MessagingStyle addMessage(CharSequence text, long timestamp, CharSequence sender) {
+ return addMessage(text, timestamp,
+ sender == null ? null : new Person().setName(sender));
+ }
+
+ /**
+ * Adds a message for display by this notification. Convenience call for a simple
+ * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}.
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender The {@link Person} who sent the message.
+ * Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert the user set in {@code MessagingStyle(Person)}.
+ *
+ * @see Message#Message(CharSequence, long, CharSequence)
+ *
+ * @return this object for method chaining
+ */
+ public MessagingStyle addMessage(CharSequence text, long timestamp, Person sender) {
return addMessage(new Message(text, timestamp, sender));
}
@@ -6083,6 +6196,7 @@
/**
* Sets whether this conversation notification represents a group.
+ *
* @param isGroupConversation {@code true} if the conversation represents a group,
* {@code false} otherwise.
* @return this object for method chaining
@@ -6093,9 +6207,27 @@
}
/**
- * Returns {@code true} if this notification represents a group conversation.
+ * Returns {@code true} if this notification represents a group conversation, otherwise
+ * {@code false}.
+ *
+ * <p> If the application that generated this {@link MessagingStyle} targets an SDK version
+ * less than {@link Build.VERSION_CODES#P}, this method becomes dependent on whether or
+ * not the conversation title is set; returning {@code true} if the conversation title is
+ * a non-null value, or {@code false} otherwise. From {@link Build.VERSION_CODES#P} forward,
+ * this method returns what's set by {@link #setGroupConversation(boolean)} allowing for
+ * named, non-group conversations.
+ *
+ * @see #setConversationTitle(CharSequence)
*/
public boolean isGroupConversation() {
+ // When target SDK version is < P, a non-null conversation title dictates if this is
+ // as group conversation.
+ if (mBuilder != null
+ && mBuilder.mContext.getApplicationInfo().targetSdkVersion
+ < Build.VERSION_CODES.P) {
+ return mConversationTitle != null;
+ }
+
return mIsGroupConversation;
}
@@ -6105,8 +6237,10 @@
@Override
public void addExtras(Bundle extras) {
super.addExtras(extras);
- if (mUserDisplayName != null) {
- extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUserDisplayName);
+ if (mUser != null) {
+ // For legacy usages
+ extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUser.getName());
+ extras.putParcelable(EXTRA_MESSAGING_PERSON, mUser);
}
if (mConversationTitle != null) {
extras.putCharSequence(EXTRA_CONVERSATION_TITLE, mConversationTitle);
@@ -6126,14 +6260,15 @@
Message m = findLatestIncomingMessage();
CharSequence text = (m == null) ? null : m.mText;
CharSequence sender = m == null ? null
- : TextUtils.isEmpty(m.mSender) ? mUserDisplayName : m.mSender;
+ : m.mSender == null || TextUtils.isEmpty(m.mSender.getName())
+ ? mUser.getName() : m.mSender.getName();
CharSequence title;
if (!TextUtils.isEmpty(mConversationTitle)) {
if (!TextUtils.isEmpty(sender)) {
BidiFormatter bidi = BidiFormatter.getInstance();
title = mBuilder.mContext.getString(
com.android.internal.R.string.notification_messaging_title_template,
- bidi.unicodeWrap(mConversationTitle), bidi.unicodeWrap(m.mSender));
+ bidi.unicodeWrap(mConversationTitle), bidi.unicodeWrap(sender));
} else {
title = mConversationTitle;
}
@@ -6156,7 +6291,11 @@
protected void restoreFromExtras(Bundle extras) {
super.restoreFromExtras(extras);
- mUserDisplayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME);
+ mUser = extras.getParcelable(EXTRA_MESSAGING_PERSON);
+ if (mUser == null) {
+ CharSequence displayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME);
+ mUser = new Person().setName(displayName);
+ }
mConversationTitle = extras.getCharSequence(EXTRA_CONVERSATION_TITLE);
Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
mMessages = Message.getMessagesFromBundleArray(messages);
@@ -6172,7 +6311,7 @@
public RemoteViews makeContentView(boolean increasedHeight) {
mBuilder.mOriginalActions = mBuilder.mActions;
mBuilder.mActions = new ArrayList<>();
- RemoteViews remoteViews = makeBigContentView();
+ RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
mBuilder.mActions = mBuilder.mOriginalActions;
mBuilder.mOriginalActions = null;
return remoteViews;
@@ -6191,7 +6330,7 @@
for (int i = messages.size() - 1; i >= 0; i--) {
Message m = messages.get(i);
// Incoming messages have a non-empty sender.
- if (!TextUtils.isEmpty(m.mSender)) {
+ if (m.mSender != null && !TextUtils.isEmpty(m.mSender.getName())) {
return m;
}
}
@@ -6207,23 +6346,31 @@
*/
@Override
public RemoteViews makeBigContentView() {
+ return makeBigContentView(false /* showRightIcon */);
+ }
+
+ @NonNull
+ private RemoteViews makeBigContentView(boolean showRightIcon) {
CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
? super.mBigContentTitle
: mConversationTitle;
boolean isOneToOne = TextUtils.isEmpty(conversationTitle);
- if (isOneToOne) {
- // Let's add the conversationTitle in case we didn't have one before and all
- // messages are from the same sender
- conversationTitle = createConversationTitleFromMessages();
- } else if (hasOnlyWhiteSpaceSenders()) {
+ if (hasOnlyWhiteSpaceSenders()) {
isOneToOne = true;
}
- boolean hasTitle = !TextUtils.isEmpty(conversationTitle);
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
- .hideLargeIcon(isOneToOne).alwaysShowReply(true));
+ .hideLargeIcon(!showRightIcon || isOneToOne)
+ .headerTextSecondary(conversationTitle)
+ .alwaysShowReply(showRightIcon));
addExtras(mBuilder.mN.extras);
+ // also update the end margin if there is an image
+ int endMargin = R.dimen.notification_content_margin_end;
+ if (mBuilder.mN.hasLargeIcon() && showRightIcon) {
+ endMargin = R.dimen.notification_content_plus_picture_margin_end;
+ }
+ contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.resolveContrastColor());
contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
@@ -6238,8 +6385,8 @@
private boolean hasOnlyWhiteSpaceSenders() {
for (int i = 0; i < mMessages.size(); i++) {
Message m = mMessages.get(i);
- CharSequence sender = m.getSender();
- if (!isWhiteSpace(sender)) {
+ Person sender = m.getSenderPerson();
+ if (sender != null && !isWhiteSpace(sender.getName())) {
return false;
}
}
@@ -6268,9 +6415,9 @@
ArraySet<CharSequence> names = new ArraySet<>();
for (int i = 0; i < mMessages.size(); i++) {
Message m = mMessages.get(i);
- CharSequence sender = m.getSender();
+ Person sender = m.getSenderPerson();
if (sender != null) {
- names.add(sender);
+ names.add(sender.getName());
}
}
SpannableStringBuilder title = new SpannableStringBuilder();
@@ -6290,7 +6437,7 @@
*/
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
- RemoteViews remoteViews = makeBigContentView();
+ RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
return remoteViews;
}
@@ -6305,13 +6452,15 @@
static final String KEY_TEXT = "text";
static final String KEY_TIMESTAMP = "time";
static final String KEY_SENDER = "sender";
+ static final String KEY_SENDER_PERSON = "sender_person";
static final String KEY_DATA_MIME_TYPE = "type";
static final String KEY_DATA_URI= "uri";
static final String KEY_EXTRAS_BUNDLE = "extras";
private final CharSequence mText;
private final long mTimestamp;
- private final CharSequence mSender;
+ @Nullable
+ private final Person mSender;
private Bundle mExtras = new Bundle();
private String mDataMimeType;
@@ -6326,8 +6475,28 @@
* the platform will insert {@link MessagingStyle#getUserDisplayName()}.
* Should be unique amongst all individuals in the conversation, and should be
* consistent during re-posts of the notification.
+ *
+ * @deprecated use {@code Message(CharSequence, long, Person)}
*/
public Message(CharSequence text, long timestamp, CharSequence sender){
+ this(text, timestamp, sender == null ? null : new Person().setName(sender));
+ }
+
+ /**
+ * Constructor
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender The {@link Person} who sent the message.
+ * Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert the user set in {@code MessagingStyle(Person)}.
+ * <p>
+ * The person provided should contain an Icon, set with {@link Person#setIcon(Icon)}
+ * and also have a name provided with {@link Person#setName(CharSequence)}. If multiple
+ * users have the same name, consider providing a key with {@link Person#setKey(String)}
+ * in order to differentiate between the different users.
+ * </p>
+ */
+ public Message(CharSequence text, long timestamp, @Nullable Person sender){
mText = text;
mTimestamp = timestamp;
mSender = sender;
@@ -6390,8 +6559,18 @@
/**
* Get the text used to display the contact's name in the messaging experience
+ *
+ * @deprecated use {@link #getSenderPerson()}
*/
public CharSequence getSender() {
+ return mSender == null ? null : mSender.getName();
+ }
+
+ /**
+ * Get the sender associated with this message.
+ */
+ @Nullable
+ public Person getSenderPerson() {
return mSender;
}
@@ -6417,7 +6596,9 @@
}
bundle.putLong(KEY_TIMESTAMP, mTimestamp);
if (mSender != null) {
- bundle.putCharSequence(KEY_SENDER, mSender);
+ // Legacy listeners need this
+ bundle.putCharSequence(KEY_SENDER, mSender.getName());
+ bundle.putParcelable(KEY_SENDER_PERSON, mSender);
}
if (mDataMimeType != null) {
bundle.putString(KEY_DATA_MIME_TYPE, mDataMimeType);
@@ -6466,8 +6647,20 @@
if (!bundle.containsKey(KEY_TEXT) || !bundle.containsKey(KEY_TIMESTAMP)) {
return null;
} else {
+
+ Person senderPerson = bundle.getParcelable(KEY_SENDER_PERSON);
+ if (senderPerson == null) {
+ // Legacy apps that use compat don't actually provide the sender objects
+ // We need to fix the compat version to provide people / use
+ // the native api instead
+ CharSequence senderName = bundle.getCharSequence(KEY_SENDER);
+ if (senderName != null) {
+ senderPerson = new Person().setName(senderName);
+ }
+ }
Message message = new Message(bundle.getCharSequence(KEY_TEXT),
- bundle.getLong(KEY_TIMESTAMP), bundle.getCharSequence(KEY_SENDER));
+ bundle.getLong(KEY_TIMESTAMP),
+ senderPerson);
if (bundle.containsKey(KEY_DATA_MIME_TYPE) &&
bundle.containsKey(KEY_DATA_URI)) {
message.setData(bundle.getString(KEY_DATA_MIME_TYPE),
@@ -7102,6 +7295,176 @@
}
}
+ /**
+ * A Person associated with this Notification.
+ */
+ public static final class Person implements Parcelable {
+ @Nullable private CharSequence mName;
+ @Nullable private Icon mIcon;
+ @Nullable private String mUri;
+ @Nullable private String mKey;
+
+ protected Person(Parcel in) {
+ mName = in.readCharSequence();
+ if (in.readInt() != 0) {
+ mIcon = Icon.CREATOR.createFromParcel(in);
+ }
+ mUri = in.readString();
+ mKey = in.readString();
+ }
+
+ /**
+ * Create a new person.
+ */
+ public Person() {
+ }
+
+ /**
+ * Give this person a name.
+ *
+ * @param name the name of this person
+ */
+ public Person setName(@Nullable CharSequence name) {
+ this.mName = name;
+ return this;
+ }
+
+ /**
+ * Add an icon for this person.
+ * <br />
+ * This is currently only used for {@link MessagingStyle} notifications and should not be
+ * provided otherwise, in order to save memory. The system will prefer this icon over any
+ * images that are resolved from the URI.
+ *
+ * @param icon the icon of the person
+ */
+ public Person setIcon(@Nullable Icon icon) {
+ this.mIcon = icon;
+ return this;
+ }
+
+ /**
+ * Set a URI associated with this person.
+ *
+ * <P>
+ * Depending on user preferences, adding a URI to a Person may allow the notification to
+ * pass through interruption filters, if this notification is of
+ * category {@link #CATEGORY_CALL} or {@link #CATEGORY_MESSAGE}.
+ * The addition of people may also cause this notification to appear more prominently in
+ * the user interface.
+ * </P>
+ *
+ * <P>
+ * The person should be specified by the {@code String} representation of a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
+ * </P>
+ *
+ * <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema
+ * URIs. The path part of these URIs must exist in the contacts database, in the
+ * appropriate column, or the reference will be discarded as invalid. Telephone schema
+ * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
+ * </P>
+ *
+ * @param uri a URI for the person
+ */
+ public Person setUri(@Nullable String uri) {
+ mUri = uri;
+ return this;
+ }
+
+ /**
+ * Add a key to this person in order to uniquely identify it.
+ * This is especially useful if the name doesn't uniquely identify this person or if the
+ * display name is a short handle of the actual name.
+ *
+ * <P>If no key is provided, the name serves as as the key for the purpose of
+ * identification.</P>
+ *
+ * @param key the key that uniquely identifies this person
+ */
+ public Person setKey(@Nullable String key) {
+ mKey = key;
+ return this;
+ }
+
+
+ /**
+ * @return the uri provided for this person or {@code null} if no Uri was provided
+ */
+ @Nullable
+ public String getUri() {
+ return mUri;
+ }
+
+ /**
+ * @return the name provided for this person or {@code null} if no name was provided
+ */
+ @Nullable
+ public CharSequence getName() {
+ return mName;
+ }
+
+ /**
+ * @return the icon provided for this person or {@code null} if no icon was provided
+ */
+ @Nullable
+ public Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * @return the key provided for this person or {@code null} if no key was provided
+ */
+ @Nullable
+ public String getKey() {
+ return mKey;
+ }
+
+ /**
+ * @return the URI associated with this person, or "name:mName" otherwise
+ * @hide
+ */
+ public String resolveToLegacyUri() {
+ if (mUri != null) {
+ return mUri;
+ }
+ if (mName != null) {
+ return "name:" + mName;
+ }
+ return "";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, @WriteFlags int flags) {
+ dest.writeCharSequence(mName);
+ if (mIcon != null) {
+ dest.writeInt(1);
+ mIcon.writeToParcel(dest, 0);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeString(mUri);
+ dest.writeString(mKey);
+ }
+
+ public static final Creator<Person> CREATOR = new Creator<Person>() {
+ @Override
+ public Person createFromParcel(Parcel in) {
+ return new Person(in);
+ }
+
+ @Override
+ public Person[] newArray(int size) {
+ return new Person[size];
+ }
+ };
+ }
+
// When adding a new Style subclass here, don't forget to update
// Builder.getNotificationStyleClass.
@@ -8541,6 +8904,7 @@
boolean ambient = false;
CharSequence title;
CharSequence text;
+ CharSequence headerTextSecondary;
boolean hideLargeIcon;
public boolean alwaysShowReply;
@@ -8549,6 +8913,7 @@
ambient = false;
title = null;
text = null;
+ headerTextSecondary = null;
return this;
}
@@ -8567,6 +8932,11 @@
return this;
}
+ final StandardTemplateParams headerTextSecondary(CharSequence text) {
+ this.headerTextSecondary = text;
+ return this;
+ }
+
final StandardTemplateParams alwaysShowReply(boolean alwaysShowReply) {
this.alwaysShowReply = alwaysShowReply;
return this;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 2e697ac..aa05b76 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -29,10 +29,14 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.security.KeyChain;
+import libcore.util.NonNull;
+import libcore.util.Nullable;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -438,6 +442,31 @@
// TO DO: describe syntax.
public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
+ /**
+ * Broadcast action: notify the newly transferred administrator that the transfer
+ * from the original administrator was successful.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_TRANSFER_OWNERSHIP_COMPLETE =
+ "android.app.action.TRANSFER_OWNERSHIP_COMPLETE";
+
+ /**
+ * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
+ * allows a mobile device management application to pass data to the management application
+ * instance after owner transfer.
+ *
+ * <p>
+ * If the transfer is successful, the new device owner receives the data in
+ * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)}.
+ * The bundle is not changed during the ownership transfer.
+ *
+ * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
+ */
+ public static final String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE =
+ "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
+
private DevicePolicyManager mManager;
private ComponentName mWho;
@@ -860,6 +889,20 @@
}
/**
+ * Called on the newly assigned owner (either device owner or profile owner) when the ownership
+ * transfer has completed successfully.
+ *
+ * <p> The {@code bundle} parameter allows the original owner to pass data
+ * to the new one.
+ *
+ * @param context the running context as per {@link #onReceive}
+ * @param bundle the data to be passed to the new owner
+ */
+ public void onTransferOwnershipComplete(@NonNull Context context,
+ @Nullable PersistableBundle bundle) {
+ }
+
+ /**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
* convenience callbacks for each action.
@@ -921,6 +964,10 @@
onUserAdded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
} else if (ACTION_USER_REMOVED.equals(action)) {
onUserRemoved(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
+ } else if (ACTION_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) {
+ PersistableBundle bundle =
+ intent.getParcelableExtra(EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE);
+ onTransferOwnershipComplete(context, bundle);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0b74741..ab85fdc 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1124,6 +1124,7 @@
*
* This broadcast is sent only to the primary user.
* @see #ACTION_PROVISION_MANAGED_DEVICE
+ * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DEVICE_OWNER_CHANGED
@@ -1709,6 +1710,16 @@
public static final int ID_TYPE_MEID = 8;
/**
+ * Broadcast action: sent when the profile owner is set, changed or cleared.
+ *
+ * This broadcast is sent only to the user managed by the new profile owner.
+ * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PROFILE_OWNER_CHANGED =
+ "android.app.action.PROFILE_OWNER_CHANGED";
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
@@ -7518,7 +7529,8 @@
}
/**
- * Called by a device owner to disable the keyguard altogether.
+ * Called by a device owner or profile owner of secondary users that is affiliated with the
+ * device to disable the keyguard altogether.
* <p>
* Setting the keyguard to disabled has the same effect as choosing "None" as the screen lock
* type. However, this call has no effect if a password, pin or pattern is currently set. If a
@@ -7533,7 +7545,10 @@
* @param disabled {@code true} disables the keyguard, {@code false} reenables it.
* @return {@code false} if attempting to disable the keyguard while a lock password was in
* place. {@code true} otherwise.
- * @throws SecurityException if {@code admin} is not a device owner.
+ * @throws SecurityException if {@code admin} is not the device owner, or a profile owner of
+ * secondary user that is affiliated with the device.
+ * @see #isAffiliatedUser
+ * @see #getSecondaryUsers
*/
public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setKeyguardDisabled");
@@ -7545,9 +7560,9 @@
}
/**
- * Called by device owner to disable the status bar. Disabling the status bar blocks
- * notifications, quick settings and other screen overlays that allow escaping from a single use
- * device.
+ * Called by device owner or profile owner of secondary users that is affiliated with the
+ * device to disable the status bar. Disabling the status bar blocks notifications, quick
+ * settings and other screen overlays that allow escaping from a single use device.
* <p>
* <strong>Note:</strong> This method has no effect for LockTask mode. The behavior of the
* status bar in LockTask mode can be configured with
@@ -7558,7 +7573,10 @@
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled {@code true} disables the status bar, {@code false} reenables it.
* @return {@code false} if attempting to disable the status bar failed. {@code true} otherwise.
- * @throws SecurityException if {@code admin} is not a device owner.
+ * @throws SecurityException if {@code admin} is not the device owner, or a profile owner of
+ * secondary user that is affiliated with the device.
+ * @see #isAffiliatedUser
+ * @see #getSecondaryUsers
*/
public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setStatusBarDisabled");
@@ -8990,41 +9008,34 @@
}
}
- //TODO STOPSHIP Add link to onTransferComplete callback when implemented.
/**
- * Transfers the current administrator. All policies from the current administrator are
- * migrated to the new administrator. The whole operation is atomic - the transfer is either
- * complete or not done at all.
+ * Changes the current administrator to another one. All policies from the current
+ * administrator are migrated to the new administrator. The whole operation is atomic -
+ * the transfer is either complete or not done at all.
*
- * Depending on the current administrator (device owner, profile owner, corporate owned
- * profile owner), you have the following expected behaviour:
+ * <p>Depending on the current administrator (device owner, profile owner), you have the
+ * following expected behaviour:
* <ul>
* <li>A device owner can only be transferred to a new device owner</li>
* <li>A profile owner can only be transferred to a new profile owner</li>
- * <li>A corporate owned managed profile can have two cases:
- * <ul>
- * <li>If the device owner and profile owner are the same package,
- * both will be transferred.</li>
- * <li>If the device owner and profile owner are different packages,
- * and if this method is called from the profile owner, only the profile owner
- * is transferred. Similarly, if it is called from the device owner, only
- * the device owner is transferred.</li>
- * </ul>
- * </li>
* </ul>
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param target Which {@link DeviceAdminReceiver} we want the new administrator to be.
- * @param bundle Parameters - This bundle allows the current administrator to pass data to the
- * new administrator. The parameters will be received in the
- * onTransferComplete callback.
- * @hide
+ * <p>Use the {@code bundle} parameter to pass data to the new administrator. The parameters
+ * will be received in the
+ * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)} callback.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with
+ * @param target which {@link DeviceAdminReceiver} we want the new administrator to be
+ * @param bundle data to be sent to the new administrator
+ * @throws SecurityException if {@code admin} is not a device owner nor a profile owner
+ * @throws IllegalArgumentException if {@code admin} or {@code target} is {@code null},
+ * both are components in the same package or {@code target} is not an active admin
*/
- public void transferOwner(@NonNull ComponentName admin, @NonNull ComponentName target,
+ public void transferOwnership(@NonNull ComponentName admin, @NonNull ComponentName target,
PersistableBundle bundle) {
- throwIfParentInstance("transferOwner");
+ throwIfParentInstance("transferOwnership");
try {
- mService.transferOwner(admin, target, bundle);
+ mService.transferOwnership(admin, target, bundle);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5916a62..1d8ddee 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -387,5 +387,5 @@
boolean isLogoutEnabled();
List<String> getDisallowedSystemApps(in ComponentName admin, int userId, String provisioningAction);
- void transferOwner(in ComponentName admin, in ComponentName target, in PersistableBundle bundle);
+ void transferOwnership(in ComponentName admin, in ComponentName target, in PersistableBundle bundle);
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 6512b98..3a6a5b2 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -707,7 +707,6 @@
* redirects them into main-thread actions. This serializes the backup
* progress callbacks nicely within the usual main-thread lifecycle pattern.
*/
- @SystemApi
private class BackupObserverWrapper extends IBackupObserver.Stub {
final Handler mHandler;
final BackupObserver mObserver;
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index c42a898..792cb5f 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -402,6 +402,9 @@
/**
* Ask the framework whether this app is eligible for backup.
*
+ * <p>If you are calling this method multiple times, you should instead use
+ * {@link #filterAppsEligibleForBackup(String[])} to save resources.
+ *
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
*
* @param packageName The name of the package.
@@ -410,6 +413,16 @@
boolean isAppEligibleForBackup(String packageName);
/**
+ * Filter the packages that are eligible for backup and return the result.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @param packages The list of packages to filter.
+ * @return The packages eligible for backup.
+ */
+ String[] filterAppsEligibleForBackup(in String[] packages);
+
+ /**
* Request an immediate backup, providing an observer to which results of the backup operation
* will be published. The Android backup system will decide for each package whether it will
* be full app data backup or key/value-pair-based backup.
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 764ceed..7703c6b 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -24,6 +24,8 @@
import android.os.Parcelable;
import android.os.RemoteException;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -78,7 +80,8 @@
}
/** Get the target state lifecycle request. */
- ActivityLifecycleItem getLifecycleStateRequest() {
+ @VisibleForTesting
+ public ActivityLifecycleItem getLifecycleStateRequest() {
return mLifecycleStateRequest;
}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 4b4fe72..93e14de 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -16,6 +16,7 @@
package android.app.usage;
+import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.content.ComponentName;
import android.content.res.Configuration;
@@ -37,7 +38,7 @@
* @param eventType The event that occurred. Valid values can be found at
* {@link UsageEvents}
*/
- public abstract void reportEvent(ComponentName component, int userId, int eventType);
+ public abstract void reportEvent(ComponentName component, @UserIdInt int userId, int eventType);
/**
* Reports an event to the UsageStatsManager.
@@ -47,14 +48,14 @@
* @param eventType The event that occurred. Valid values can be found at
* {@link UsageEvents}
*/
- public abstract void reportEvent(String packageName, int userId, int eventType);
+ public abstract void reportEvent(String packageName, @UserIdInt int userId, int eventType);
/**
* Reports a configuration change to the UsageStatsManager.
*
* @param config The new device configuration.
*/
- public abstract void reportConfigurationChange(Configuration config, int userId);
+ public abstract void reportConfigurationChange(Configuration config, @UserIdInt int userId);
/**
* Reports that an action equivalent to a ShortcutInfo is taken by the user.
@@ -65,7 +66,8 @@
*
* @see android.content.pm.ShortcutManager#reportShortcutUsed(String)
*/
- public abstract void reportShortcutUsage(String packageName, String shortcutId, int userId);
+ public abstract void reportShortcutUsage(String packageName, String shortcutId,
+ @UserIdInt int userId);
/**
* Reports that a content provider has been accessed by a foreground app.
@@ -73,7 +75,8 @@
* @param pkgName The package name of the content provider
* @param userId The user in which the content provider was accessed.
*/
- public abstract void reportContentProviderUsage(String name, String pkgName, int userId);
+ public abstract void reportContentProviderUsage(String name, String pkgName,
+ @UserIdInt int userId);
/**
* Prepares the UsageStatsService for shutdown.
@@ -89,7 +92,7 @@
* @param userId
* @return
*/
- public abstract boolean isAppIdle(String packageName, int uidForAppId, int userId);
+ public abstract boolean isAppIdle(String packageName, int uidForAppId, @UserIdInt int userId);
/**
* Returns the app standby bucket that the app is currently in. This accessor does
@@ -101,15 +104,15 @@
* @return the AppStandby bucket code the app currently resides in. If the app is
* unknown in the given user, STANDBY_BUCKET_NEVER is returned.
*/
- @StandbyBuckets public abstract int getAppStandbyBucket(String packageName, int userId,
- long nowElapsed);
+ @StandbyBuckets public abstract int getAppStandbyBucket(String packageName,
+ @UserIdInt int userId, long nowElapsed);
/**
* Returns all of the uids for a given user where all packages associating with that uid
* are in the app idle state -- there are no associated apps that are not idle. This means
* all of the returned uids can be safely considered app idle.
*/
- public abstract int[] getIdleUidsForUser(int userId);
+ public abstract int[] getIdleUidsForUser(@UserIdInt int userId);
/**
* @return True if currently app idle parole mode is on. This means all idle apps are allow to
@@ -134,8 +137,8 @@
public static abstract class AppIdleStateChangeListener {
/** Callback to inform listeners that the idle state has changed to a new bucket. */
- public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle,
- int bucket);
+ public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
+ boolean idle, int bucket);
/**
* Callback to inform listeners that the parole state has changed. This means apps are
@@ -144,10 +147,16 @@
public abstract void onParoleStateChanged(boolean isParoleOn);
}
- /* Backup/Restore API */
- public abstract byte[] getBackupPayload(int user, String key);
+ /** Backup/Restore API */
+ public abstract byte[] getBackupPayload(@UserIdInt int userId, String key);
- public abstract void applyRestoredPayload(int user, String key, byte[] payload);
+ /**
+ * ?
+ * @param userId
+ * @param key
+ * @param payload
+ */
+ public abstract void applyRestoredPayload(@UserIdInt int userId, String key, byte[] payload);
/**
* Return usage stats.
@@ -155,6 +164,29 @@
* @param obfuscateInstantApps whether instant app package names need to be obfuscated in the
* result.
*/
- public abstract List<UsageStats> queryUsageStatsForUser(
- int userId, int interval, long beginTime, long endTime, boolean obfuscateInstantApps);
+ public abstract List<UsageStats> queryUsageStatsForUser(@UserIdInt int userId, int interval,
+ long beginTime, long endTime, boolean obfuscateInstantApps);
+
+ /**
+ * Used to persist the last time a job was run for this app, in order to make decisions later
+ * whether a job should be deferred until later. The time passed in should be in elapsed
+ * realtime since boot.
+ * @param packageName the app that executed a job.
+ * @param userId the user associated with the job.
+ * @param elapsedRealtime the time when the job was executed, in elapsed realtime millis since
+ * boot.
+ */
+ public abstract void setLastJobRunTime(String packageName, @UserIdInt int userId,
+ long elapsedRealtime);
+
+ /**
+ * Returns the time in millis since a job was executed for this app, in elapsed realtime
+ * timebase. This value can be larger than the current elapsed realtime if the job was executed
+ * before the device was rebooted. The default value is {@link Long#MAX_VALUE}.
+ * @param packageName the app you're asking about.
+ * @param userId the user associated with the job.
+ * @return the time in millis since a job was last executed for the app, provided it was
+ * indicated here before by a call to {@link #setLastJobRunTime(String, int, long)}.
+ */
+ public abstract long getTimeSinceLastJobRun(String packageName, @UserIdInt int userId);
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 37bb6b0..a55bbda 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -677,6 +677,34 @@
}
/**
+ * Updates the info for the supplied AppWidget provider.
+ *
+ * <p>
+ * The manifest entry of the provider should contain an additional meta-data tag similar to
+ * {@link #META_DATA_APPWIDGET_PROVIDER} which should point to any additional definitions for
+ * the provider.
+ *
+ * <p>
+ * This is persisted across device reboots and app updates. If this meta-data key is not
+ * present in the manifest entry, the info reverts to default.
+ *
+ * @param provider {@link ComponentName} for the {@link
+ * android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget.
+ * @param metaDataKey key for the meta-data tag pointing to the new provider info. Use null
+ * to reset any previously set info.
+ */
+ public void updateAppWidgetProviderInfo(ComponentName provider, @Nullable String metaDataKey) {
+ if (mService == null) {
+ return;
+ }
+ try {
+ mService.updateAppWidgetProviderInfo(provider, metaDataKey);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Notifies the specified collection view in all the specified AppWidget instances
* to invalidate their data.
*
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 7841b83..35a21a4 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -103,6 +104,24 @@
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
/**
+ * Intent used to broadcast the selection of a connected device as active.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_ACTIVE_DEVICE_CHANGED =
+ "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
+
+ /**
* Intent used to broadcast the change in the Audio Codec state of the
* A2DP Source profile.
*
@@ -425,6 +444,75 @@
}
/**
+ * Select a connected device as active.
+ *
+ * The active device selection is per profile. An active device's
+ * purpose is profile-specific. For example, A2DP audio streaming
+ * is to the active A2DP Sink device. If a remote device is not
+ * connected, it cannot be selected as active.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is not connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that the
+ * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+ * with the active device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device the remote Bluetooth device. Could be null to clear
+ * the active device and stop streaming audio to a Bluetooth device.
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+ if (DBG) log("setActiveDevice(" + device + ")");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && ((device == null) || isValidDevice(device))) {
+ return mService.setActiveDevice(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Get the connected device that is active.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+ * permission.
+ *
+ * @return the connected device that is active or null if no device
+ * is active
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @Nullable
+ public BluetoothDevice getActiveDevice() {
+ if (VDBG) log("getActiveDevice()");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ return mService.getActiveDevice();
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return null;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Set priority of the profile
*
* <p> The device should already be paired.
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 838d315..c94540a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -93,6 +94,23 @@
public static final String ACTION_AUDIO_STATE_CHANGED =
"android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
+ /**
+ * Intent used to broadcast the selection of a connected device as active.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_ACTIVE_DEVICE_CHANGED =
+ "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
/**
* Intent used to broadcast that the headset has posted a
@@ -983,9 +1001,105 @@
}
/**
- * check if in-band ringing is supported for this platform.
+ * Select a connected device as active.
*
- * @return true if in-band ringing is supported false if in-band ringing is not supported
+ * The active device selection is per profile. An active device's
+ * purpose is profile-specific. For example, in HFP and HSP profiles,
+ * it is the device used for phone call audio. If a remote device is not
+ * connected, it cannot be selected as active.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is not connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that the
+ * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+ * with the active device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Remote Bluetooth Device, could be null if phone call audio should not be
+ * streamed to a headset
+ * @return false on immediate error, true otherwise
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+ if (DBG) {
+ Log.d(TAG, "setActiveDevice: " + device);
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && (device == null || isValidDevice(device))) {
+ try {
+ return service.setActiveDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ }
+
+ /**
+ * Get the connected device that is active.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+ * permission.
+ *
+ * @return the connected device that is active or null if no device
+ * is active.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+ public BluetoothDevice getActiveDevice() {
+ if (VDBG) {
+ Log.d(TAG, "getActiveDevice");
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
+ try {
+ return service.getActiveDevice();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return null;
+ }
+
+ /**
+ * Check if in-band ringing is currently enabled. In-band ringing could be disabled during an
+ * active connection.
+ *
+ * @return true if in-band ringing is enabled, false if in-band ringing is disabled
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+ public boolean isInbandRingingEnabled() {
+ if (DBG) {
+ log("isInbandRingingEnabled()");
+ }
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
+ try {
+ return service.isInbandRingingEnabled();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ }
+
+ /**
+ * Check if in-band ringing is supported for this platform.
+ *
+ * @return true if in-band ringing is supported, false if in-band ringing is not supported
* @hide
*/
public static boolean isInbandRingingSupported(Context context) {
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index df2028a..41cf809 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -157,12 +157,19 @@
public static final int HID_DEVICE = 19;
/**
+ * Object Push Profile (OPP)
+ *
+ * @hide
+ */
+ public static final int OPP = 20;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- public static final int MAX_PROFILE_ID = 19;
+ public static final int MAX_PROFILE_ID = 20;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 9323261..94e1e2d 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -34,16 +34,18 @@
import android.text.TextUtils;
import android.text.style.URLSpan;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
+import libcore.io.IoUtils;
+
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
-import libcore.io.IoUtils;
/**
* Representation of a clipped data on the clipboard.
@@ -665,6 +667,25 @@
b.append("NULL");
}
}
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ if (mHtmlText != null) {
+ proto.write(ClipDataProto.Item.HTML_TEXT, mHtmlText);
+ } else if (mText != null) {
+ proto.write(ClipDataProto.Item.TEXT, mText.toString());
+ } else if (mUri != null) {
+ proto.write(ClipDataProto.Item.URI, mUri.toString());
+ } else if (mIntent != null) {
+ mIntent.writeToProto(proto, ClipDataProto.Item.INTENT, true, true, true, true);
+ } else {
+ proto.write(ClipDataProto.Item.NOTHING, true);
+ }
+
+ proto.end(token);
+ }
}
/**
@@ -1048,6 +1069,26 @@
}
/** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ if (mClipDescription != null) {
+ mClipDescription.writeToProto(proto, ClipDataProto.DESCRIPTION);
+ }
+ if (mIcon != null) {
+ final long iToken = proto.start(ClipDataProto.ICON);
+ proto.write(ClipDataProto.Icon.WIDTH, mIcon.getWidth());
+ proto.write(ClipDataProto.Icon.HEIGHT, mIcon.getHeight());
+ proto.end(iToken);
+ }
+ for (int i = 0; i < mItems.size(); i++) {
+ mItems.get(i).writeToProto(proto, ClipDataProto.ITEMS);
+ }
+
+ proto.end(token);
+ }
+
+ /** @hide */
public void collectUris(List<Uri> out) {
for (int i = 0; i < mItems.size(); ++i) {
ClipData.Item item = getItemAt(i);
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index 8e30fd6..19295fc 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -21,6 +21,7 @@
import android.os.PersistableBundle;
import android.text.TextUtils;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
@@ -337,6 +338,28 @@
return !first;
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ final int size = mMimeTypes.size();
+ for (int i = 0; i < size; i++) {
+ proto.write(ClipDescriptionProto.MIME_TYPES, mMimeTypes.get(i));
+ }
+
+ if (mLabel != null) {
+ proto.write(ClipDescriptionProto.LABEL, mLabel.toString());
+ }
+ if (mExtras != null) {
+ mExtras.writeToProto(proto, ClipDescriptionProto.EXTRAS);
+ }
+ if (mTimeStamp > 0) {
+ proto.write(ClipDescriptionProto.TIMESTAMP_MS, mTimeStamp);
+ }
+
+ proto.end(token);
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
index 0d36bdd..ead6c25 100644
--- a/core/java/android/content/ComponentName.java
+++ b/core/java/android/content/ComponentName.java
@@ -284,9 +284,11 @@
}
/** Put this here so that individual services don't have to reimplement this. @hide */
- public void toProto(ProtoOutputStream proto) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
proto.write(ComponentNameProto.PACKAGE_NAME, mPackage);
proto.write(ComponentNameProto.CLASS_NAME, mClass);
+ proto.end(token);
}
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4cedeaa..1a0d5aa 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2851,10 +2851,12 @@
* {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
* {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
* {@link #BIND_WAIVE_PRIORITY}.
- * @return If you have successfully bound to the service, {@code true} is returned;
- * {@code false} is returned if the connection is not made so you will not
- * receive the service object. You should still call {@link #unbindService}
- * to release the connection even if this method returned {@code false}.
+ * @return {@code true} if the system is in the process of bringing up a
+ * service that your client has permission to bind to; {@code false}
+ * if the system couldn't find the service or if your client doesn't
+ * have permission to bind to it. If this value is {@code true}, you
+ * should later call {@link #unbindService} to release the
+ * connection.
*
* @throws SecurityException If the caller does not have permission to access the service
* or the service can not be found.
@@ -3221,7 +3223,7 @@
public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.PowerManager} for controlling power management,
* including "wake locks," which let you keep the device on while
* you're running long tasks.
@@ -3229,117 +3231,117 @@
public static final String POWER_SERVICE = "power";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.RecoverySystem} for accessing the recovery system
* service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @hide
*/
public static final String RECOVERY_SERVICE = "recovery";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.WindowManager} for accessing the system's window
* manager.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.view.WindowManager
*/
public static final String WINDOW_SERVICE = "window";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.LayoutInflater} for inflating layout resources in this
* context.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.view.LayoutInflater
*/
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.accounts.AccountManager} for receiving intents at a
* time of your choosing.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.accounts.AccountManager
*/
public static final String ACCOUNT_SERVICE = "account";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.ActivityManager} for interacting with the global
* system state.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.ActivityManager
*/
public static final String ACTIVITY_SERVICE = "activity";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.AlarmManager} for receiving intents at a
* time of your choosing.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.AlarmManager
*/
public static final String ALARM_SERVICE = "alarm";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.NotificationManager} for informing the user of
* background events.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.NotificationManager
*/
public static final String NOTIFICATION_SERVICE = "notification";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.accessibility.AccessibilityManager} for giving the user
* feedback for UI events through the registered event listeners.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.view.accessibility.AccessibilityManager
*/
public static final String ACCESSIBILITY_SERVICE = "accessibility";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.accessibility.CaptioningManager} for obtaining
* captioning properties and listening for changes in captioning
* preferences.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.view.accessibility.CaptioningManager
*/
public static final String CAPTIONING_SERVICE = "captioning";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.NotificationManager} for controlling keyguard.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.KeyguardManager
*/
public static final String KEYGUARD_SERVICE = "keyguard";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.location.LocationManager} for controlling location
* updates.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.location.LocationManager
*/
public static final String LOCATION_SERVICE = "location";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.location.CountryDetector} for detecting the country that
* the user is in.
*
@@ -3348,96 +3350,96 @@
public static final String COUNTRY_DETECTOR = "country_detector";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.SearchManager} for handling searches.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.SearchManager
*/
public static final String SEARCH_SERVICE = "search";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.hardware.SensorManager} for accessing sensors.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.SensorManager
*/
public static final String SENSOR_SERVICE = "sensor";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.os.storage.StorageManager} for accessing system storage
* functions.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.os.storage.StorageManager
*/
public static final String STORAGE_SERVICE = "storage";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.usage.StorageStatsManager} for accessing system storage
* statistics.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.usage.StorageStatsManager
*/
public static final String STORAGE_STATS_SERVICE = "storagestats";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* com.android.server.WallpaperService for accessing wallpapers.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String WALLPAPER_SERVICE = "wallpaper";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.os.Vibrator} for interacting with the vibration hardware.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.os.Vibrator
*/
public static final String VIBRATOR_SERVICE = "vibrator";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.StatusBarManager} for interacting with the status bar.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.StatusBarManager
* @hide
*/
public static final String STATUS_BAR_SERVICE = "statusbar";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.ConnectivityManager} for handling management of
* network connections.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.ConnectivityManager
*/
public static final String CONNECTIVITY_SERVICE = "connectivity";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with
* IPSec.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String IPSEC_SERVICE = "ipsec";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.os.IUpdateLock} for managing runtime sequences that
* must not be interrupted by headless OTA application or similar.
*
* @hide
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.os.UpdateLock
*/
public static final String UPDATE_LOCK_SERVICE = "updatelock";
@@ -3449,18 +3451,18 @@
public static final String NETWORKMANAGEMENT_SERVICE = "network_management";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link com.android.server.slice.SliceManagerService} for managing slices.
* @hide
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String SLICE_SERVICE = "slice";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.usage.NetworkStatsManager} for querying network usage stats.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.usage.NetworkStatsManager
*/
public static final String NETWORK_STATS_SERVICE = "netstats";
@@ -3470,40 +3472,40 @@
public static final String NETWORK_WATCHLIST_SERVICE = "network_watchlist";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.wifi.WifiManager} for handling management of
* Wi-Fi access.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.WifiManager
*/
public static final String WIFI_SERVICE = "wifi";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.wifi.p2p.WifiP2pManager} for handling management of
* Wi-Fi peer-to-peer connections.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.p2p.WifiP2pManager
*/
public static final String WIFI_P2P_SERVICE = "wifip2p";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.wifi.aware.WifiAwareManager} for handling management of
* Wi-Fi Aware.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.aware.WifiAwareManager
*/
public static final String WIFI_AWARE_SERVICE = "wifiaware";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.wifi.WifiScanner} for scanning the wifi universe
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.WifiScanner
* @hide
*/
@@ -3511,10 +3513,10 @@
public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.wifi.RttManager} for ranging devices with wifi
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.RttManager
* @hide
*/
@@ -3522,24 +3524,23 @@
public static final String WIFI_RTT_SERVICE = "rttmanager";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.wifi.rtt.WifiRttManager} for ranging devices with wifi
*
* Note: this is a replacement for WIFI_RTT_SERVICE above. It will
* be renamed once final implementation in place.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.wifi.rtt.WifiRttManager
- * @hide
*/
- public static final String WIFI_RTT_RANGING_SERVICE = "rttmanager2";
+ public static final String WIFI_RTT_RANGING_SERVICE = "wifirtt";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.lowpan.LowpanManager} for handling management of
* LoWPAN access.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.lowpan.LowpanManager
*
* @hide
@@ -3547,11 +3548,11 @@
public static final String LOWPAN_SERVICE = "lowpan";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.EthernetManager} for handling management of
* Ethernet access.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.EthernetManager
*
* @hide
@@ -3559,98 +3560,98 @@
public static final String ETHERNET_SERVICE = "ethernet";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.net.nsd.NsdManager} for handling management of network service
* discovery
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.nsd.NsdManager
*/
public static final String NSD_SERVICE = "servicediscovery";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.AudioManager} for handling management of volume,
* ringer modes and audio routing.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.media.AudioManager
*/
public static final String AUDIO_SERVICE = "audio";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.fingerprint.FingerprintManager} for handling management
* of fingerprints.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.fingerprint.FingerprintManager
*/
public static final String FINGERPRINT_SERVICE = "fingerprint";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.MediaRouter} for controlling and managing
* routing of media.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.media.MediaRouter
*/
public static final String MEDIA_ROUTER_SERVICE = "media_router";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.session.MediaSessionManager} for managing media Sessions.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.media.session.MediaSessionManager
*/
public static final String MEDIA_SESSION_SERVICE = "media_session";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.telephony.TelephonyManager} for handling management the
* telephony features of the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.telephony.TelephonyManager
*/
public static final String TELEPHONY_SERVICE = "phone";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.telephony.SubscriptionManager} for handling management the
* telephony subscriptions of the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.telephony.SubscriptionManager
*/
public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.telecom.TelecomManager} to manage telecom-related features
* of the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.telecom.TelecomManager
*/
public static final String TELECOM_SERVICE = "telecom";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.telephony.CarrierConfigManager} for reading carrier configuration values.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.telephony.CarrierConfigManager
*/
public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.telephony.euicc.EuiccManager} to manage the device eUICC (embedded SIM).
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.telephony.euicc.EuiccManager
* TODO(b/35851809): Unhide this API.
* @hide
@@ -3658,47 +3659,47 @@
public static final String EUICC_SERVICE = "euicc_service";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.ClipboardManager} for accessing and modifying
* the contents of the global clipboard.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.content.ClipboardManager
*/
public static final String CLIPBOARD_SERVICE = "clipboard";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link TextClassificationManager} for text classification services.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see TextClassificationManager
*/
public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.inputmethod.InputMethodManager} for accessing input
* methods.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String INPUT_METHOD_SERVICE = "input_method";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.textservice.TextServicesManager} for accessing
* text services.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String APPWIDGET_SERVICE = "appwidget";
@@ -3706,7 +3707,7 @@
* Official published name of the (internal) voice interaction manager service.
*
* @hide
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
@@ -3714,119 +3715,119 @@
* Official published name of the (internal) autofill service.
*
* @hide
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
/**
- * Use with {@link #getSystemService} to access the
+ * Use with {@link #getSystemService(String)} to access the
* {@link com.android.server.voiceinteraction.SoundTriggerService}.
*
* @hide
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";
/**
- * Use with {@link #getSystemService} to retrieve an
+ * Use with {@link #getSystemService(String)} to retrieve an
* {@link android.app.backup.IBackupManager IBackupManager} for communicating
* with the backup mechanism.
* @hide
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
@SystemApi
public static final String BACKUP_SERVICE = "backup";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.DropBoxManager} instance for recording
* diagnostic logs.
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String DROPBOX_SERVICE = "dropbox";
/**
* System service name for the DeviceIdleController. There is no Java API for this.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @hide
*/
public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.admin.DevicePolicyManager} for working with global
* device policy management.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String DEVICE_POLICY_SERVICE = "device_policy";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.UiModeManager} for controlling UI modes.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String UI_MODE_SERVICE = "uimode";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.DownloadManager} for requesting HTTP downloads.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String DOWNLOAD_SERVICE = "download";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.BatteryManager} for managing battery state.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String BATTERY_SERVICE = "batterymanager";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.nfc.NfcManager} for using NFC.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String NFC_SERVICE = "nfc";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.bluetooth.BluetoothManager} for using Bluetooth.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.sip.SipManager} for accessing the SIP related service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
/** @hide */
public static final String SIP_SERVICE = "sip";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.hardware.usb.UsbManager} for access to USB devices (as a USB host)
* and for controlling this device's behavior as a USB device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.usb.UsbManager
*/
public static final String USB_SERVICE = "usb";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.hardware.SerialManager} for access to serial ports.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.SerialManager
*
* @hide
@@ -3834,11 +3835,11 @@
public static final String SERIAL_SERVICE = "serial";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.hdmi.HdmiControlManager} for controlling and managing
* HDMI-CEC protocol.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.hdmi.HdmiControlManager
* @hide
*/
@@ -3846,67 +3847,67 @@
public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.input.InputManager} for interacting with input devices.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.input.InputManager
*/
public static final String INPUT_SERVICE = "input";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.display.DisplayManager} for interacting with display devices.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.display.DisplayManager
*/
public static final String DISPLAY_SERVICE = "display";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.UserManager} for managing users on devices that support multiple users.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.os.UserManager
*/
public static final String USER_SERVICE = "user";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.pm.LauncherApps} for querying and monitoring launchable apps across
* profiles of a user.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.content.pm.LauncherApps
*/
public static final String LAUNCHER_APPS_SERVICE = "launcherapps";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.RestrictionsManager} for retrieving application restrictions
* and requesting permissions for restricted operations.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.content.RestrictionsManager
*/
public static final String RESTRICTIONS_SERVICE = "restrictions";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.AppOpsManager} for tracking application operations
* on the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.AppOpsManager
*/
public static final String APP_OPS_SERVICE = "appops";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.camera2.CameraManager} for interacting with
* camera devices.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.camera2.CameraManager
*/
public static final String CAMERA_SERVICE = "camera";
@@ -3915,51 +3916,51 @@
* {@link android.print.PrintManager} for printing and managing
* printers and print tasks.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.print.PrintManager
*/
public static final String PRINT_SERVICE = "print";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.companion.CompanionDeviceManager} for managing companion devices
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.companion.CompanionDeviceManager
*/
public static final String COMPANION_DEVICE_SERVICE = "companiondevice";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.ConsumerIrManager} for transmitting infrared
* signals from the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.ConsumerIrManager
*/
public static final String CONSUMER_IR_SERVICE = "consumer_ir";
/**
* {@link android.app.trust.TrustManager} for managing trust agents.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.trust.TrustManager
* @hide
*/
public static final String TRUST_SERVICE = "trust";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.tv.TvInputManager} for interacting with TV inputs
* on the device.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.media.tv.TvInputManager
*/
public static final String TV_INPUT_SERVICE = "tv_input";
/**
* {@link android.net.NetworkScoreManager} for managing network scoring.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.net.NetworkScoreManager
* @hide
*/
@@ -3967,29 +3968,29 @@
public static final String NETWORK_SCORE_SERVICE = "network_score";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.usage.UsageStatsManager} for querying device usage stats.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.usage.UsageStatsManager
*/
public static final String USAGE_STATS_SERVICE = "usagestats";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.app.job.JobScheduler} instance for managing occasional
* background tasks.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.app.job.JobScheduler
*/
public static final String JOB_SCHEDULER_SERVICE = "jobscheduler";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.service.persistentdata.PersistentDataBlockManager} instance
* for interacting with a storage device that lives across factory resets.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.service.persistentdata.PersistentDataBlockManager
* @hide
*/
@@ -3997,10 +3998,10 @@
public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.service.oemlock.OemLockManager} instance for managing the OEM lock.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.service.oemlock.OemLockManager
* @hide
*/
@@ -4008,54 +4009,54 @@
public static final String OEM_LOCK_SERVICE = "oem_lock";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.media.projection.MediaProjectionManager} instance for managing
* media projection sessions.
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.media.projection.MediaProjectionManager
*/
public static final String MEDIA_PROJECTION_SERVICE = "media_projection";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.media.midi.MidiManager} for accessing the MIDI service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String MIDI_SERVICE = "midi";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.radio.RadioManager} for accessing the broadcast radio service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @hide
*/
public static final String RADIO_SERVICE = "broadcastradio";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.HardwarePropertiesManager} for accessing the hardware properties service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.content.pm.ShortcutManager
*/
public static final String SHORTCUT_SERVICE = "shortcut";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.hardware.location.ContextHubManager} for accessing context hubs.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.hardware.location.ContextHubManager
*
* @hide
@@ -4064,11 +4065,11 @@
public static final String CONTEXTHUB_SERVICE = "contexthub";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.os.health.SystemHealthManager} for accessing system health (battery, power,
* memory, etc) metrics.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
@@ -4097,46 +4098,46 @@
public static final String STATS_COMPANION_SERVICE = "statscompanion";
/**
- * Use with {@link #getSystemService} to retrieve an {@link android.stats.StatsManager}.
+ * Use with {@link #getSystemService(String)} to retrieve an {@link android.stats.StatsManager}.
* @hide
*/
@SystemApi
public static final String STATS_MANAGER = "stats";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.content.om.OverlayManager} for managing overlay packages.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @see android.content.om.OverlayManager
* @hide
*/
public static final String OVERLAY_SERVICE = "overlay";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link VrManager} for accessing the VR service.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
* @hide
*/
@SystemApi
public static final String VR_SERVICE = "vrmanager";
/**
- * Use with {@link #getSystemService} to retrieve an
+ * Use with {@link #getSystemService(String)} to retrieve an
* {@link android.app.timezone.ITimeZoneRulesManager}.
* @hide
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String TIME_ZONE_RULES_MANAGER_SERVICE = "timezone";
/**
- * Use with {@link #getSystemService} to retrieve a
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.pm.crossprofile.CrossProfileApps} for cross profile operations.
*
- * @see #getSystemService
+ * @see #getSystemService(String)
*/
public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e940769..6e99709 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -9410,6 +9410,12 @@
}
/** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ // Same input parameters that toString() gives to toShortString().
+ writeToProto(proto, fieldId, true, true, true, false);
+ }
+
+ /** @hide */
public void writeToProto(ProtoOutputStream proto, long fieldId, boolean secure, boolean comp,
boolean extras, boolean clip) {
long token = proto.start(fieldId);
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index c16dbbe..21398f6 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -31,6 +31,11 @@
* the {@link android.os.IBinder} of the communication channel to the
* Service.
*
+ * <p class="note"><b>Note:</b> If the system has started to bind your
+ * client app to a service, it's possible that your app will never receive
+ * this callback. Your app won't receive a callback if there's an issue with
+ * the service, such as the service crashing while being created.
+ *
* @param name The concrete component name of the service that has
* been connected.
*
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index cee2599..8014c94 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.PackageParser.Package;
import android.os.Build;
@@ -56,7 +58,7 @@
boolean apacheHttpLegacyPresent = isLibraryPresent(
usesLibraries, usesOptionalLibraries, APACHE_HTTP_LEGACY);
if (!apacheHttpLegacyPresent) {
- usesLibraries = ArrayUtils.add(usesLibraries, APACHE_HTTP_LEGACY);
+ usesLibraries = prefix(usesLibraries, APACHE_HTTP_LEGACY);
}
}
@@ -86,4 +88,12 @@
return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
|| ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
}
+
+ private static @NonNull <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
+ if (cur == null) {
+ cur = new ArrayList<>();
+ }
+ cur.add(0, val);
+ return cur;
+ }
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5f82c2a..6cd4285 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2327,8 +2327,6 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports Wi-Fi RTT (IEEE 802.11mc).
- *
- * @hide RTT_API
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_WIFI_RTT = "android.hardware.wifi.rtt";
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 8839cf9..ea476b0 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -181,6 +181,11 @@
public static final int DISABLED_REASON_APP_CHANGED = 2;
/**
+ * Shortcut is disabled for an unknown reason.
+ */
+ public static final int DISABLED_REASON_UNKNOWN = 3;
+
+ /**
* A disabled reason that's equal to or bigger than this is due to backup and restore issue.
* A shortcut with such a reason wil be visible to the launcher, but not to the publisher.
* ({@link #isVisibleToPublisher()} will be false.)
@@ -214,6 +219,7 @@
DISABLED_REASON_NOT_DISABLED,
DISABLED_REASON_BY_APP,
DISABLED_REASON_APP_CHANGED,
+ DISABLED_REASON_UNKNOWN,
DISABLED_REASON_VERSION_LOWER,
DISABLED_REASON_BACKUP_NOT_SUPPORTED,
DISABLED_REASON_SIGNATURE_MISMATCH,
@@ -272,6 +278,9 @@
case DISABLED_REASON_OTHER_RESTORE_ISSUE:
return res.getString(
com.android.internal.R.string.shortcut_restore_unknown_issue);
+ case DISABLED_REASON_UNKNOWN:
+ return res.getString(
+ com.android.internal.R.string.shortcut_disabled_reason_unknown);
}
return null;
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 5a63896..1201ef4 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1149,36 +1149,33 @@
/**
* <p>Position of the camera optical center.</p>
* <p>The position of the camera device's lens optical center,
- * as a three-dimensional vector <code>(x,y,z)</code>, relative to the
- * optical center of the largest camera device facing in the
- * same direction as this camera, in the {@link android.hardware.SensorEvent Android sensor coordinate
- * axes}. Note that only the axis definitions are shared with
- * the sensor coordinate system, but not the origin.</p>
- * <p>If this device is the largest or only camera device with a
- * given facing, then this position will be <code>(0, 0, 0)</code>; a
- * camera device with a lens optical center located 3 cm from
- * the main sensor along the +X axis (to the right from the
- * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
- * <p>To transform a pixel coordinates between two cameras
- * facing the same direction, first the source camera
- * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then
- * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
- * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
- * of the source camera, the translation of the source camera
- * relative to the destination camera, the
- * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
- * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
- * of the destination camera. This obtains a
- * radial-distortion-free coordinate in the destination
- * camera pixel coordinates.</p>
- * <p>To compare this against a real image from the destination
- * camera, the destination camera image then needs to be
- * corrected for radial distortion before comparison or
- * sampling.</p>
+ * as a three-dimensional vector <code>(x,y,z)</code>.</p>
+ * <p>Prior to Android P, or when {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is PRIMARY_CAMERA, this position
+ * is relative to the optical center of the largest camera device facing in the same
+ * direction as this camera, in the {@link android.hardware.SensorEvent Android sensor
+ * coordinate axes}. Note that only the axis definitions are shared with the sensor
+ * coordinate system, but not the origin.</p>
+ * <p>If this device is the largest or only camera device with a given facing, then this
+ * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm
+ * from the main sensor along the +X axis (to the right from the user's perspective) will
+ * report <code>(0.03, 0, 0)</code>.</p>
+ * <p>To transform a pixel coordinates between two cameras facing the same direction, first
+ * the source camera {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then the source
+ * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the
+ * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the source camera, the translation of the source camera
+ * relative to the destination camera, the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination
+ * camera, and finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} of the destination
+ * camera. This obtains a radial-distortion-free coordinate in the destination camera pixel
+ * coordinates.</p>
+ * <p>To compare this against a real image from the destination camera, the destination camera
+ * image then needs to be corrected for radial distortion before comparison or sampling.</p>
+ * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to
+ * the center of the primary gyroscope on the device.</p>
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_RADIAL_DISTORTION
*/
@@ -1289,6 +1286,28 @@
new Key<float[]>("android.lens.radialDistortion", float[].class);
/**
+ * <p>The origin for {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}.</p>
+ * <p>Different calibration methods and use cases can produce better or worse results
+ * depending on the selected coordinate origin.</p>
+ * <p>For devices designed to support the MOTION_TRACKING capability, the GYROSCOPE origin
+ * makes device calibration and later usage by applications combining camera and gyroscope
+ * information together simpler.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #LENS_POSE_REFERENCE_PRIMARY_CAMERA PRIMARY_CAMERA}</li>
+ * <li>{@link #LENS_POSE_REFERENCE_GYROSCOPE GYROSCOPE}</li>
+ * </ul></p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see #LENS_POSE_REFERENCE_PRIMARY_CAMERA
+ * @see #LENS_POSE_REFERENCE_GYROSCOPE
+ */
+ @PublicKey
+ public static final Key<Integer> LENS_POSE_REFERENCE =
+ new Key<Integer>("android.lens.poseReference", int.class);
+
+ /**
* <p>List of noise reduction modes for {@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} that are supported
* by this camera device.</p>
* <p>Full-capability camera devices will always support OFF and FAST.</p>
@@ -1559,6 +1578,7 @@
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT DEPTH_OUTPUT}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO CONSTRAINED_HIGH_SPEED_VIDEO}</li>
+ * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1573,6 +1593,7 @@
* @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
* @see #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
* @see #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+ * @see #REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING
*/
@PublicKey
public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -1643,7 +1664,7 @@
* time-consuming hardware re-configuration or internal camera pipeline
* change. For performance reasons we advise clients to pass their initial
* values as part of
- * {@link SessionConfiguration#setSessionParameters }.i
+ * {@link SessionConfiguration#setSessionParameters }.
* Once the camera capture session is enabled it is also recommended to avoid
* changing them from their initial values set in
* {@link SessionConfiguration#setSessionParameters }.
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 87e503d..ce1fba7 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -144,6 +144,37 @@
*/
public static final int TEMPLATE_MANUAL = 6;
+ /**
+ * A template for selecting camera parameters that match TEMPLATE_PREVIEW as closely as
+ * possible while improving the camera output for motion tracking use cases.
+ *
+ * <p>This template is best used by applications that are frequently switching between motion
+ * tracking use cases and regular still capture use cases, to minimize the IQ changes
+ * when swapping use cases.</p>
+ *
+ * <p>This template is guaranteed to be supported on camera devices that support the
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}
+ * capability.</p>
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_MOTION_TRACKING_PREVIEW = 7;
+
+ /**
+ * A template for selecting camera parameters that maximize the quality of camera output for
+ * motion tracking use cases.
+ *
+ * <p>This template is best used by applications dedicated to motion tracking applications,
+ * which aren't concerned about fast switches between motion tracking and other use cases.</p>
+ *
+ * <p>This template is guaranteed to be supported on camera devices that support the
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}
+ * capability.</p>
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_MOTION_TRACKING_BEST = 8;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"TEMPLATE_"}, value =
@@ -386,6 +417,24 @@
* </table><br>
* </p>
*
+ * <p>MOTION_TRACKING-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
+ * includes
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING})
+ * devices support at least the below stream combinations in addition to those for
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices. The
+ * {@code FULL FOV 640} entry means that the device will support a resolution that's 640 pixels
+ * wide, with the height set so that the resolution aspect ratio matches the MAXIMUM output
+ * aspect ratio. So for a device with a 4:3 image sensor, this will be 640x480, and for a
+ * device with a 16:9 sensor, this will be 640x360, and so on.
+ *
+ * <table>
+ * <tr><th colspan="7">MOTION_TRACKING-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code FULL FOV 640}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Live preview with a tracking YUV output and a maximum-resolution YUV for still captures.</td> </tr>
+ * </table><br>
+ * </p>
+ *
* <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
* support at least the below stream combinations in addition to those for
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index cb11d0f..1c7f289 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -336,6 +336,30 @@
public static final int LENS_FACING_EXTERNAL = 2;
//
+ // Enumeration values for CameraCharacteristics#LENS_POSE_REFERENCE
+ //
+
+ /**
+ * <p>The value of {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} is relative to the optical center of
+ * the largest camera device facing the same direction as this camera.</p>
+ * <p>This default value for API levels before Android P.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
+ */
+ public static final int LENS_POSE_REFERENCE_PRIMARY_CAMERA = 0;
+
+ /**
+ * <p>The value of {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation} is relative to the position of the
+ * primary gyroscope of this Android device.</p>
+ * <p>This is the value reported by all devices that support the MOTION_TRACKING capability.</p>
+ *
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
+ */
+ public static final int LENS_POSE_REFERENCE_GYROSCOPE = 1;
+
+ //
// Enumeration values for CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
//
@@ -665,6 +689,7 @@
* </ul>
* </li>
* <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
+ * <li>As of Android P, the {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} entry is listed by this device.</li>
* <li>A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support
* normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16
* format.</li>
@@ -680,6 +705,7 @@
* @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
* @see CameraCharacteristics#LENS_FACING
* @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
* @see CameraCharacteristics#LENS_RADIAL_DISTORTION
@@ -774,6 +800,51 @@
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9;
+ /**
+ * <p>The device supports controls and metadata required for accurate motion tracking for
+ * use cases such as augmented reality, electronic image stabilization, and so on.</p>
+ * <p>This means this camera device has accurate optical calibration and timestamps relative
+ * to the inertial sensors.</p>
+ * <p>This capability requires the camera device to support the following:</p>
+ * <ul>
+ * <li>Capture request templates {@link android.hardware.camera2.CameraDevice#TEMPLATE_MOTION_TRACKING_PREVIEW } and {@link android.hardware.camera2.CameraDevice#TEMPLATE_MOTION_TRACKING_BEST } are defined.</li>
+ * <li>The stream configurations listed in {@link android.hardware.camera2.CameraDevice#createCaptureSession } for MOTION_TRACKING are
+ * supported, either at 30 or 60fps maximum frame rate.</li>
+ * <li>The following camera characteristics and capture result metadata are provided:<ul>
+ * <li>{@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}</li>
+ * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
+ * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
+ * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
+ * <li>{@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} with value GYROSCOPE</li>
+ * </ul>
+ * </li>
+ * <li>The {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} field has value <code>REALTIME</code>. When compared to
+ * timestamps from the device's gyroscopes, the clock difference for events occuring at
+ * the same actual time instant will be less than 1 ms.</li>
+ * <li>The value of the {@link CaptureResult#SENSOR_ROLLING_SHUTTER_SKEW android.sensor.rollingShutterSkew} field is accurate to within 1 ms.</li>
+ * <li>The value of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime} is guaranteed to be available in the
+ * capture result.</li>
+ * <li>The {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} control supports MOTION_TRACKING to limit maximum
+ * exposure to 20 milliseconds.</li>
+ * <li>The stream configurations required for MOTION_TRACKING (listed at {@link android.hardware.camera2.CameraDevice#createCaptureSession }) can operate at least at
+ * 30fps; optionally, they can operate at 60fps, and '[60, 60]' is listed in
+ * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}.</li>
+ * </ul>
+ *
+ * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
+ * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+ * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
+ * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
+ * @see CaptureResult#SENSOR_ROLLING_SHUTTER_SKEW
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ public static final int REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10;
+
//
// Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
//
@@ -1661,6 +1732,16 @@
*/
public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6;
+ /**
+ * <p>This request is for a motion tracking use case, where
+ * the application will use camera and inertial sensor data to
+ * locate and track objects in the world.</p>
+ * <p>The camera device auto-exposure routine will limit the exposure time
+ * of the camera to no more than 20 milliseconds, to minimize motion blur.</p>
+ * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+ */
+ public static final int CONTROL_CAPTURE_INTENT_MOTION_TRACKING = 7;
+
//
// Enumeration values for CaptureRequest#CONTROL_EFFECT_MODE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 77da2a5..cf27c70 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1487,10 +1487,13 @@
* strategy.</p>
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
- * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains PRIVATE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are
- * always supported.</p>
+ * <p>All intents are supported by all devices, except that:
+ * * ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * PRIVATE_REPROCESSING or YUV_REPROCESSING.
+ * * MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * MANUAL_SENSOR.
+ * * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * MOTION_TRACKING.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
@@ -1500,6 +1503,7 @@
* <li>{@link #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT VIDEO_SNAPSHOT}</li>
* <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
* <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li>
+ * <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1512,6 +1516,7 @@
* @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
* @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
* @see #CONTROL_CAPTURE_INTENT_MANUAL
+ * @see #CONTROL_CAPTURE_INTENT_MOTION_TRACKING
*/
@PublicKey
public static final Key<Integer> CONTROL_CAPTURE_INTENT =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 6d7b06f..b6b0c90 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1754,10 +1754,13 @@
* strategy.</p>
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
- * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains PRIVATE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are
- * always supported.</p>
+ * <p>All intents are supported by all devices, except that:
+ * * ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * PRIVATE_REPROCESSING or YUV_REPROCESSING.
+ * * MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * MANUAL_SENSOR.
+ * * MOTION_TRACKING will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
+ * MOTION_TRACKING.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
@@ -1767,6 +1770,7 @@
* <li>{@link #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT VIDEO_SNAPSHOT}</li>
* <li>{@link #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG ZERO_SHUTTER_LAG}</li>
* <li>{@link #CONTROL_CAPTURE_INTENT_MANUAL MANUAL}</li>
+ * <li>{@link #CONTROL_CAPTURE_INTENT_MOTION_TRACKING MOTION_TRACKING}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1779,6 +1783,7 @@
* @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
* @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
* @see #CONTROL_CAPTURE_INTENT_MANUAL
+ * @see #CONTROL_CAPTURE_INTENT_MOTION_TRACKING
*/
@PublicKey
public static final Key<Integer> CONTROL_CAPTURE_INTENT =
@@ -2761,36 +2766,33 @@
/**
* <p>Position of the camera optical center.</p>
* <p>The position of the camera device's lens optical center,
- * as a three-dimensional vector <code>(x,y,z)</code>, relative to the
- * optical center of the largest camera device facing in the
- * same direction as this camera, in the {@link android.hardware.SensorEvent Android sensor coordinate
- * axes}. Note that only the axis definitions are shared with
- * the sensor coordinate system, but not the origin.</p>
- * <p>If this device is the largest or only camera device with a
- * given facing, then this position will be <code>(0, 0, 0)</code>; a
- * camera device with a lens optical center located 3 cm from
- * the main sensor along the +X axis (to the right from the
- * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
- * <p>To transform a pixel coordinates between two cameras
- * facing the same direction, first the source camera
- * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then
- * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
- * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
- * of the source camera, the translation of the source camera
- * relative to the destination camera, the
- * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
- * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
- * of the destination camera. This obtains a
- * radial-distortion-free coordinate in the destination
- * camera pixel coordinates.</p>
- * <p>To compare this against a real image from the destination
- * camera, the destination camera image then needs to be
- * corrected for radial distortion before comparison or
- * sampling.</p>
+ * as a three-dimensional vector <code>(x,y,z)</code>.</p>
+ * <p>Prior to Android P, or when {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is PRIMARY_CAMERA, this position
+ * is relative to the optical center of the largest camera device facing in the same
+ * direction as this camera, in the {@link android.hardware.SensorEvent Android sensor
+ * coordinate axes}. Note that only the axis definitions are shared with the sensor
+ * coordinate system, but not the origin.</p>
+ * <p>If this device is the largest or only camera device with a given facing, then this
+ * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm
+ * from the main sensor along the +X axis (to the right from the user's perspective) will
+ * report <code>(0.03, 0, 0)</code>.</p>
+ * <p>To transform a pixel coordinates between two cameras facing the same direction, first
+ * the source camera {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for. Then the source
+ * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the
+ * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the source camera, the translation of the source camera
+ * relative to the destination camera, the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination
+ * camera, and finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} of the destination
+ * camera. This obtains a radial-distortion-free coordinate in the destination camera pixel
+ * coordinates.</p>
+ * <p>To compare this against a real image from the destination camera, the destination camera
+ * image then needs to be corrected for radial distortion before comparison or sampling.</p>
+ * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to
+ * the center of the primary gyroscope on the device.</p>
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
+ * @see CameraCharacteristics#LENS_POSE_REFERENCE
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_RADIAL_DISTORTION
*/
diff --git a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
index 6fe13ca..d7c2e1b 100644
--- a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
@@ -187,7 +187,6 @@
* Base class for time-related information.
* @hide
*/
- @SystemApi
/* package */ static class TimeUnit {
/* package */ final int mHour;
/* package */ final int mMinute;
diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java
index bca2ae6..2a4ad00 100644
--- a/core/java/android/hardware/location/ContextHubMessage.java
+++ b/core/java/android/hardware/location/ContextHubMessage.java
@@ -19,14 +19,20 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
import java.util.Arrays;
/**
+ * @deprecated Use {@link android.hardware.location.NanoAppMessage} instead to send messages with
+ * {@link android.hardware.location.ContextHubClient#sendMessageToNanoApp(
+ * NanoAppMessage)} and receive messages with
+ * {@link android.hardware.location.ContextHubClientCallback#onMessageFromNanoApp(
+ * ContextHubClient, NanoAppMessage)}.
+ *
* @hide
*/
@SystemApi
+@Deprecated
public class ContextHubMessage {
private int mType;
private int mVersion;
@@ -34,7 +40,6 @@
private static final String TAG = "ContextHubMessage";
-
/**
* Get the message type
*
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index 0465def..b5c01ec 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -28,9 +28,14 @@
* Nano apps are expected to be used only by bundled apps only
* at this time.
*
+ * @deprecated Use {@link android.hardware.location.NanoAppBinary} instead to load a nanoapp with
+ * {@link android.hardware.location.ContextHubManager#loadNanoApp(
+ * ContextHubInfo, NanoAppBinary)}.
+ *
* @hide
*/
@SystemApi
+@Deprecated
public class NanoApp {
private final String TAG = "NanoApp";
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
index 5ccf546..75a96ee 100644
--- a/core/java/android/hardware/location/NanoAppFilter.java
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -16,15 +16,18 @@
package android.hardware.location;
-
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
+ * @deprecated Use {@link android.hardware.location.ContextHubManager#queryNanoApps(ContextHubInfo)}
+ * to find loaded nanoapps, which doesn't require using this class as a parameter.
+ *
* @hide
*/
@SystemApi
+@Deprecated
public class NanoAppFilter {
private static final String TAG = "NanoAppFilter";
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index c00819b..f1926eaa 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -28,9 +28,12 @@
*
* TODO(b/69270990) Remove this class once the old API is deprecated.
*
+ * @deprecated Use {@link android.hardware.location.NanoAppState} instead.
+ *
* @hide
*/
@SystemApi
+@Deprecated
public class NanoAppInstanceInfo {
private String mPublisher = "Unknown";
private String mName = "Unknown";
diff --git a/core/java/android/hardware/radio/ITuner.aidl b/core/java/android/hardware/radio/ITuner.aidl
index 18287fa..ca38076 100644
--- a/core/java/android/hardware/radio/ITuner.aidl
+++ b/core/java/android/hardware/radio/ITuner.aidl
@@ -82,17 +82,9 @@
*/
List<RadioManager.ProgramInfo> getProgramList(in Map vendorFilter);
- /**
- * @throws IllegalStateException if the switch is not supported at current
- * configuration.
- */
- boolean isAnalogForced();
-
- /**
- * @throws IllegalStateException if the switch is not supported at current
- * configuration.
- */
- void setAnalogForced(boolean isForced);
+ boolean isConfigFlagSupported(int flag);
+ boolean isConfigFlagSet(int flag);
+ void setConfigFlag(int flag, boolean value);
/**
* @param parameters Vendor-specific key-value pairs, must be Map<String, String>
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 9b6515c..b740f14 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -120,6 +120,71 @@
* @see BandDescriptor */
public static final int REGION_KOREA = 4;
+ /**
+ * Forces mono audio stream reception.
+ *
+ * Analog broadcasts can recover poor reception conditions by jointing
+ * stereo channels into one. Mainly for, but not limited to AM/FM.
+ */
+ public static final int CONFIG_FORCE_MONO = 1;
+ /**
+ * Forces the analog playback for the supporting radio technology.
+ *
+ * User may disable digital playback for FM HD Radio or hybrid FM/DAB with
+ * this option. This is purely user choice, ie. does not reflect digital-
+ * analog handover state managed from the HAL implementation side.
+ *
+ * Some radio technologies may not support this, ie. DAB.
+ */
+ public static final int CONFIG_FORCE_ANALOG = 2;
+ /**
+ * Forces the digital playback for the supporting radio technology.
+ *
+ * User may disable digital-analog handover that happens with poor
+ * reception conditions. With digital forced, the radio will remain silent
+ * instead of switching to analog channel if it's available. This is purely
+ * user choice, it does not reflect the actual state of handover.
+ */
+ public static final int CONFIG_FORCE_DIGITAL = 3;
+ /**
+ * RDS Alternative Frequencies.
+ *
+ * If set and the currently tuned RDS station broadcasts on multiple
+ * channels, radio tuner automatically switches to the best available
+ * alternative.
+ */
+ public static final int CONFIG_RDS_AF = 4;
+ /**
+ * RDS region-specific program lock-down.
+ *
+ * Allows user to lock to the current region as they move into the
+ * other region.
+ */
+ public static final int CONFIG_RDS_REG = 5;
+ /** Enables DAB-DAB hard- and implicit-linking (the same content). */
+ public static final int CONFIG_DAB_DAB_LINKING = 6;
+ /** Enables DAB-FM hard- and implicit-linking (the same content). */
+ public static final int CONFIG_DAB_FM_LINKING = 7;
+ /** Enables DAB-DAB soft-linking (related content). */
+ public static final int CONFIG_DAB_DAB_SOFT_LINKING = 8;
+ /** Enables DAB-FM soft-linking (related content). */
+ public static final int CONFIG_DAB_FM_SOFT_LINKING = 9;
+
+ /** @hide */
+ @IntDef(prefix = { "CONFIG_" }, value = {
+ CONFIG_FORCE_MONO,
+ CONFIG_FORCE_ANALOG,
+ CONFIG_FORCE_DIGITAL,
+ CONFIG_RDS_AF,
+ CONFIG_RDS_REG,
+ CONFIG_DAB_DAB_LINKING,
+ CONFIG_DAB_FM_LINKING,
+ CONFIG_DAB_DAB_SOFT_LINKING,
+ CONFIG_DAB_FM_SOFT_LINKING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConfigFlag {}
+
private static void writeStringMap(@NonNull Parcel dest, @NonNull Map<String, String> map) {
dest.writeInt(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
@@ -1654,8 +1719,8 @@
TunerCallbackAdapter halCallback = new TunerCallbackAdapter(callback, handler);
try {
tuner = mService.openTuner(moduleId, config, withAudio, halCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to open tuner", e);
+ } catch (RemoteException | IllegalArgumentException ex) {
+ Log.e(TAG, "Failed to open tuner", ex);
return null;
}
if (tuner == null) {
diff --git a/core/java/android/hardware/radio/RadioTuner.java b/core/java/android/hardware/radio/RadioTuner.java
index e93fd5f..0d367e7 100644
--- a/core/java/android/hardware/radio/RadioTuner.java
+++ b/core/java/android/hardware/radio/RadioTuner.java
@@ -290,7 +290,9 @@
* @throws IllegalStateException if the switch is not supported at current
* configuration.
* @return {@code true} if analog is forced, {@code false} otherwise.
+ * @deprecated Use {@link isConfigFlagSet(int)} instead.
*/
+ @Deprecated
public abstract boolean isAnalogForced();
/**
@@ -305,10 +307,50 @@
* @param isForced {@code true} to force analog, {@code false} for a default behaviour.
* @throws IllegalStateException if the switch is not supported at current
* configuration.
+ * @deprecated Use {@link setConfigFlag(int, boolean)} instead.
*/
+ @Deprecated
public abstract void setAnalogForced(boolean isForced);
/**
+ * Checks, if a given config flag is supported
+ *
+ * @param flag Flag to check.
+ * @return True, if the flag is supported.
+ */
+ public boolean isConfigFlagSupported(@RadioManager.ConfigFlag int flag) {
+ return false;
+ }
+
+ /**
+ * Fetches the current setting of a given config flag.
+ *
+ * The success/failure result is consistent with isConfigFlagSupported.
+ *
+ * @param flag Flag to fetch.
+ * @return The current value of the flag.
+ * @throws IllegalStateException if the flag is not applicable right now.
+ * @throws UnsupportedOperationException if the flag is not supported at all.
+ */
+ public boolean isConfigFlagSet(@RadioManager.ConfigFlag int flag) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets the config flag.
+ *
+ * The success/failure result is consistent with isConfigFlagSupported.
+ *
+ * @param flag Flag to set.
+ * @param value The new value of a given flag.
+ * @throws IllegalStateException if the flag is not applicable right now.
+ * @throws UnsupportedOperationException if the flag is not supported at all.
+ */
+ public void setConfigFlag(@RadioManager.ConfigFlag int flag, boolean value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Generic method for setting vendor-specific parameter values.
* The framework does not interpret the parameters, they are passed
* in an opaque manner between a vendor application and HAL.
@@ -316,6 +358,7 @@
* Framework does not make any assumptions on the keys or values, other than
* ones stated in VendorKeyValue documentation (a requirement of key
* prefixes).
+ * See VendorKeyValue at hardware/interfaces/broadcastradio/2.0/types.hal.
*
* For each pair in the result map, the key will be one of the keys
* contained in the input (possibly with wildcards expanded), and the value
@@ -332,10 +375,11 @@
*
* @param parameters Vendor-specific key-value pairs.
* @return Operation completion status for parameters being set.
- * @hide FutureFeature
*/
- public abstract @NonNull Map<String, String>
- setParameters(@NonNull Map<String, String> parameters);
+ public @NonNull Map<String, String>
+ setParameters(@NonNull Map<String, String> parameters) {
+ throw new UnsupportedOperationException();
+ }
/**
* Generic method for retrieving vendor-specific parameter values.
@@ -355,10 +399,11 @@
*
* @param keys Parameter keys to fetch.
* @return Vendor-specific key-value pairs.
- * @hide FutureFeature
*/
- public abstract @NonNull Map<String, String>
- getParameters(@NonNull List<String> keys);
+ public @NonNull Map<String, String>
+ getParameters(@NonNull List<String> keys) {
+ throw new UnsupportedOperationException();
+ }
/**
* Get current antenna connection state for current configuration.
@@ -494,7 +539,6 @@
* asynchronously.
*
* @param parameters Vendor-specific key-value pairs.
- * @hide FutureFeature
*/
public void onParametersUpdated(@NonNull Map<String, String> parameters) {}
}
diff --git a/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index 864d17c..8ad609d 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -63,6 +63,7 @@
@Override
public int setConfiguration(RadioManager.BandConfig config) {
+ if (config == null) return RadioManager.STATUS_BAD_VALUE;
try {
mTuner.setConfiguration(config);
mBand = config.getType();
@@ -235,17 +236,36 @@
@Override
public boolean isAnalogForced() {
+ return isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG);
+ }
+
+ @Override
+ public void setAnalogForced(boolean isForced) {
+ setConfigFlag(RadioManager.CONFIG_FORCE_ANALOG, isForced);
+ }
+
+ @Override
+ public boolean isConfigFlagSupported(@RadioManager.ConfigFlag int flag) {
try {
- return mTuner.isAnalogForced();
+ return mTuner.isConfigFlagSupported(flag);
} catch (RemoteException e) {
throw new RuntimeException("service died", e);
}
}
@Override
- public void setAnalogForced(boolean isForced) {
+ public boolean isConfigFlagSet(@RadioManager.ConfigFlag int flag) {
try {
- mTuner.setAnalogForced(isForced);
+ return mTuner.isConfigFlagSet(flag);
+ } catch (RemoteException e) {
+ throw new RuntimeException("service died", e);
+ }
+ }
+
+ @Override
+ public void setConfigFlag(@RadioManager.ConfigFlag int flag, boolean value) {
+ try {
+ mTuner.setConfigFlag(flag, value);
} catch (RemoteException e) {
throw new RuntimeException("service died", e);
}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 151e62d..398dda1 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -96,6 +96,11 @@
*/
void setCurrentFunction(String function, boolean usbDataUnlocked);
+ /* Sets the screen unlocked USB function(s), which will be set automatically
+ * when the screen is unlocked.
+ */
+ void setScreenUnlockedFunctions(String function);
+
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index bdb90bc..7617c2b 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -601,6 +601,32 @@
}
/**
+ * Sets the screen unlocked functions, which are persisted and set as the current functions
+ * whenever the screen is unlocked.
+ * <p>
+ * The allowed values are: {@link #USB_FUNCTION_NONE},
+ * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
+ * or {@link #USB_FUNCTION_RNDIS}.
+ * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions
+ * no longer change on screen unlock.
+ * </p><p>
+ * Note: When the screen is on, this method will apply given functions as current functions,
+ * which is asynchronous and may fail silently without applying the requested changes.
+ * </p>
+ *
+ * @param function function to set as default
+ *
+ * {@hide}
+ */
+ public void setScreenUnlockedFunctions(String function) {
+ try {
+ mService.setScreenUnlockedFunctions(function);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns a list of physical USB ports on the device.
* <p>
* This list is guaranteed to contain all dual-role USB Type C ports but it might
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 02b1c65..8937490 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -18,6 +18,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
@@ -852,6 +853,11 @@
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
+ // For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
+ // by default (but IME developers can opt this out later if they want a new behavior).
+ mWindow.getWindow().setFlags(
+ FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+
initViews();
mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
}
@@ -882,8 +888,6 @@
mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
mRootView = mInflater.inflate(
com.android.internal.R.layout.input_method, null);
- mRootView.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mWindow.setContentView(mRootView);
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index f82627b..7d752e8 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -231,6 +231,31 @@
}
}
+ /** @hide */
+ public boolean isAuthentication() {
+ switch (getName()) {
+ // Fallthrough
+ case AUTH_HMAC_MD5:
+ case AUTH_HMAC_SHA1:
+ case AUTH_HMAC_SHA256:
+ case AUTH_HMAC_SHA384:
+ case AUTH_HMAC_SHA512:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** @hide */
+ public boolean isEncryption() {
+ return getName().equals(CRYPT_AES_CBC);
+ }
+
+ /** @hide */
+ public boolean isAead() {
+ return getName().equals(AUTH_CRYPT_AES_GCM);
+ }
+
@Override
public String toString() {
return new StringBuilder()
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index e6cd3fc..f54ceb5 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -102,17 +102,11 @@
/** Set the local IP address for Tunnel mode */
public void setLocalAddress(String localAddress) {
- if (localAddress == null) {
- throw new IllegalArgumentException("localAddress may not be null!");
- }
mLocalAddress = localAddress;
}
/** Set the remote IP address for this IPsec transform */
public void setRemoteAddress(String remoteAddress) {
- if (remoteAddress == null) {
- throw new IllegalArgumentException("remoteAddress may not be null!");
- }
mRemoteAddress = remoteAddress;
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 6a4b891..34cfa9b 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -69,7 +69,7 @@
}
/** @hide */
- public static final int INVALID_RESOURCE_ID = 0;
+ public static final int INVALID_RESOURCE_ID = -1;
/**
* Thrown to indicate that a requested SPI is in use.
@@ -128,7 +128,7 @@
private final InetAddress mRemoteAddress;
private final CloseGuard mCloseGuard = CloseGuard.get();
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
- private int mResourceId;
+ private int mResourceId = INVALID_RESOURCE_ID;
/** Get the underlying SPI held by this object. */
public int getSpi() {
@@ -146,6 +146,7 @@
public void close() {
try {
mService.releaseSecurityParameterIndex(mResourceId);
+ mResourceId = INVALID_RESOURCE_ID;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -501,7 +502,7 @@
public static final class UdpEncapsulationSocket implements AutoCloseable {
private final ParcelFileDescriptor mPfd;
private final IIpSecService mService;
- private final int mResourceId;
+ private int mResourceId = INVALID_RESOURCE_ID;
private final int mPort;
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -554,6 +555,7 @@
public void close() throws IOException {
try {
mService.closeUdpEncapsulationSocket(mResourceId);
+ mResourceId = INVALID_RESOURCE_ID;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 7cd742b..102ba6d 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -347,6 +347,9 @@
*/
public IpSecTransform.Builder setSpi(
@TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
+ if (spi.getResourceId() == INVALID_RESOURCE_ID) {
+ throw new IllegalArgumentException("Invalid SecurityParameterIndex");
+ }
mConfig.setSpiResourceId(direction, spi.getResourceId());
return this;
}
@@ -381,6 +384,9 @@
public IpSecTransform.Builder setIpv4Encapsulation(
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
mConfig.setEncapType(ENCAP_ESPINUDP);
+ if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
+ throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
+ }
mConfig.setEncapSocketResourceId(localSocket.getResourceId());
mConfig.setEncapRemotePort(remotePort);
return this;
@@ -426,6 +432,9 @@
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
+ if (remoteAddress == null) {
+ throw new IllegalArgumentException("Remote address may not be null or empty!");
+ }
mConfig.setMode(MODE_TRANSPORT);
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
// FIXME: modifying a builder after calling build can change the built transform.
@@ -447,8 +456,12 @@
*/
public IpSecTransform buildTunnelModeTransform(
InetAddress localAddress, InetAddress remoteAddress) {
- // FIXME: argument validation here
- // throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
+ if (localAddress == null) {
+ throw new IllegalArgumentException("Local address may not be null or empty!");
+ }
+ if (remoteAddress == null) {
+ throw new IllegalArgumentException("Remote address may not be null or empty!");
+ }
mConfig.setLocalAddress(localAddress.getHostAddress());
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
mConfig.setMode(MODE_TUNNEL);
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 903b602..1a3ce91 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -21,6 +21,7 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.util.proto.ProtoOutputStream;
import com.android.okhttp.internalandroidapi.Dns;
import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory;
@@ -402,4 +403,11 @@
public String toString() {
return Integer.toString(netId);
}
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(NetworkProto.NET_ID, netId);
+ proto.end(token);
+ }
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index f468e5d..8b03fa8 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -20,6 +20,7 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.BitUtils;
@@ -1016,6 +1017,31 @@
return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]";
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ for (int transport : getTransportTypes()) {
+ proto.write(NetworkCapabilitiesProto.TRANSPORTS, transport);
+ }
+
+ for (int capability : getCapabilities()) {
+ proto.write(NetworkCapabilitiesProto.CAPABILITIES, capability);
+ }
+
+ proto.write(NetworkCapabilitiesProto.LINK_UP_BANDWIDTH_KBPS, mLinkUpBandwidthKbps);
+ proto.write(NetworkCapabilitiesProto.LINK_DOWN_BANDWIDTH_KBPS, mLinkDownBandwidthKbps);
+
+ if (mNetworkSpecifier != null) {
+ proto.write(NetworkCapabilitiesProto.NETWORK_SPECIFIER, mNetworkSpecifier.toString());
+ }
+
+ proto.write(NetworkCapabilitiesProto.CAN_REPORT_SIGNAL_STRENGTH, hasSignalStrength());
+ proto.write(NetworkCapabilitiesProto.SIGNAL_STRENGTH, mSignalStrength);
+
+ proto.end(token);
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 97ded2d..a072409 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -20,6 +20,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.proto.ProtoOutputStream;
import java.util.Objects;
@@ -389,6 +390,35 @@
", " + networkCapabilities.toString() + " ]";
}
+ private int typeToProtoEnum(Type t) {
+ switch (t) {
+ case NONE:
+ return NetworkRequestProto.TYPE_NONE;
+ case LISTEN:
+ return NetworkRequestProto.TYPE_LISTEN;
+ case TRACK_DEFAULT:
+ return NetworkRequestProto.TYPE_TRACK_DEFAULT;
+ case REQUEST:
+ return NetworkRequestProto.TYPE_REQUEST;
+ case BACKGROUND_REQUEST:
+ return NetworkRequestProto.TYPE_BACKGROUND_REQUEST;
+ default:
+ return NetworkRequestProto.TYPE_UNKNOWN;
+ }
+ }
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type));
+ proto.write(NetworkRequestProto.REQUEST_ID, requestId);
+ proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType);
+ networkCapabilities.writeToProto(proto, NetworkRequestProto.NETWORK_CAPABILITIES);
+
+ proto.end(token);
+ }
+
public boolean equals(Object obj) {
if (obj instanceof NetworkRequest == false) return false;
NetworkRequest that = (NetworkRequest)obj;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 196a3bc..bda720bb 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -27,6 +27,7 @@
import android.media.MediaPlayer;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.DataUnit;
import com.android.server.NetworkManagementSocketTagger;
@@ -56,15 +57,20 @@
*/
public final static int UNSUPPORTED = -1;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long KB_IN_BYTES = 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
/**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d4d74f4..77e4808 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -525,8 +525,8 @@
return ActivityManager.PROCESS_STATE_NONEXISTENT;
} else if (procState == ActivityManager.PROCESS_STATE_TOP) {
return Uid.PROCESS_STATE_TOP;
- } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
- // Persistent and other foreground states go here.
+ } else if (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+ // State when app has put itself in the foreground.
return Uid.PROCESS_STATE_FOREGROUND_SERVICE;
} else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
// Persistent and other foreground states go here.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 33470f3..eb264d6d 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -805,7 +805,7 @@
/**
* Return the total number of pairs in the map.
*/
- int size() {
+ private int size() {
int size = 0;
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
@@ -816,6 +816,24 @@
}
/**
+ * Return the total number of pairs in the map containing values that have
+ * not been cleared. More expensive than the above size function.
+ */
+ private int unclearedSize() {
+ int size = 0;
+ for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+ if (a != null) {
+ for (WeakReference<BinderProxy> ref : a) {
+ if (ref.get() != null) {
+ ++size;
+ }
+ }
+ }
+ }
+ return size;
+ }
+
+ /**
* Remove ith entry from the hash bucket indicated by hash.
*/
private void remove(int hash, int index) {
@@ -908,17 +926,31 @@
Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
+ " total = " + totalSize);
mWarnBucketSize += WARN_INCREMENT;
- if (Build.IS_DEBUGGABLE && totalSize > CRASH_AT_SIZE) {
- diagnosticCrash();
+ if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
+ // Use the number of uncleared entries to determine whether we should
+ // really report a histogram and crash. We don't want to fundamentally
+ // change behavior for a debuggable process, so we GC only if we are
+ // about to crash.
+ final int totalUnclearedSize = unclearedSize();
+ if (totalUnclearedSize >= CRASH_AT_SIZE) {
+ dumpProxyInterfaceCounts();
+ Runtime.getRuntime().gc();
+ throw new AssertionError("Binder ProxyMap has too many entries: "
+ + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
+ + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
+ } else if (totalSize > 3 * totalUnclearedSize / 2) {
+ Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
+ + (totalSize - totalUnclearedSize) + " of " + totalSize
+ + " are cleared");
+ }
}
}
}
/**
- * Dump a histogram to the logcat, then throw an assertion error. Used to diagnose
- * abnormally large proxy maps.
+ * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
*/
- private void diagnosticCrash() {
+ private void dumpProxyInterfaceCounts() {
Map<String, Integer> counts = new HashMap<>();
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
@@ -953,11 +985,6 @@
Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x"
+ sorted[i].getValue());
}
-
- // Now throw an assertion.
- final int totalSize = size();
- throw new AssertionError("Binder ProxyMap has too many entries: " + totalSize
- + ". BinderProxy leak?");
}
// Corresponding ArrayLists in the following two arrays always have the same size.
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index c58153a..7ae5a67 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -21,6 +21,7 @@
import android.util.Size;
import android.util.SizeF;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -1272,4 +1273,21 @@
}
return mMap.toString();
}
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ if (mParcelledData != null) {
+ if (isEmptyParcel()) {
+ proto.write(BundleProto.PARCELLED_DATA_SIZE, 0);
+ } else {
+ proto.write(BundleProto.PARCELLED_DATA_SIZE, mParcelledData.dataSize());
+ }
+ } else {
+ proto.write(BundleProto.MAP_DATA, mMap.toString());
+ }
+
+ proto.end(token);
+ }
}
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index a080c8d..4d7d931 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -86,6 +86,25 @@
}
/**
+ * Class which can be used to fetch an object out of a lambda. Fetching an object
+ * out of a local scope with HIDL is a common operation (although usually it can
+ * and should be avoided).
+ *
+ * @param <E> Inner object type.
+ */
+ public static final class Mutable<E> {
+ public E value;
+
+ public Mutable() {
+ value = null;
+ }
+
+ public Mutable(E value) {
+ this.value = value;
+ }
+ }
+
+ /**
* Similar to Arrays.deepHashCode, but also take care of lists.
*/
public static int deepHashCode(Object o) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index a474b47..a5e1934 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -339,7 +339,8 @@
/**
* Configure name servers, search paths, and resolver parameters for the given network.
*/
- void setDnsConfigurationForNetwork(int netId, in String[] servers, String domains);
+ void setDnsConfigurationForNetwork(int netId, in String[] servers, in String[] domains,
+ in int[] params, boolean useTls, String tlsHostname);
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index f643c57..01d6b02 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -98,4 +98,6 @@
boolean isUserNameSet(int userHandle);
boolean hasRestrictedProfiles();
boolean trySetQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
+ long getUserStartRealtime();
+ long getUserUnlockRealtime();
}
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 3ed5b17..40eceb8 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.util.ArrayMap;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.XmlUtils;
@@ -321,4 +322,21 @@
}
return mMap.toString();
}
+
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ if (mParcelledData != null) {
+ if (isEmptyParcel()) {
+ proto.write(PersistableBundleProto.PARCELLED_DATA_SIZE, 0);
+ } else {
+ proto.write(PersistableBundleProto.PARCELLED_DATA_SIZE, mParcelledData.dataSize());
+ }
+ } else {
+ proto.write(PersistableBundleProto.MAP_DATA, mMap.toString());
+ }
+
+ proto.end(token);
+ }
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 38993b7..44238df 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1392,6 +1392,34 @@
}
/**
+ * Return the time when the calling user started in elapsed milliseconds since boot,
+ * or 0 if not started.
+ *
+ * @hide
+ */
+ public long getUserStartRealtime() {
+ try {
+ return mService.getUserStartRealtime();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the time when the calling user was unlocked elapsed milliseconds since boot,
+ * or 0 if not unlocked.
+ *
+ * @hide
+ */
+ public long getUserUnlockRealtime() {
+ try {
+ return mService.getUserUnlockRealtime();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns the UserInfo object describing a specific user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param userHandle the user handle of the user whose information is being requested.
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 401b4a3..d0c2870 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -7,7 +7,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Objects;
/**
* Describes the source of some work that may be done by someone else.
@@ -162,9 +161,21 @@
@Override
public boolean equals(Object o) {
- return o instanceof WorkSource
- && !diff((WorkSource) o)
- && Objects.equals(mChains, ((WorkSource) o).mChains);
+ if (o instanceof WorkSource) {
+ WorkSource other = (WorkSource) o;
+
+ if (diff(other)) {
+ return false;
+ }
+
+ if (mChains != null && !mChains.isEmpty()) {
+ return mChains.equals(other.mChains);
+ } else {
+ return other.mChains == null || other.mChains.isEmpty();
+ }
+ }
+
+ return false;
}
@Override
@@ -407,11 +418,11 @@
}
public boolean remove(WorkSource other) {
- if (mNum <= 0 || other.mNum <= 0) {
+ if (isEmpty() || other.isEmpty()) {
return false;
}
- boolean uidRemoved = false;
+ boolean uidRemoved;
if (mNames == null && other.mNames == null) {
uidRemoved = removeUids(other);
} else {
@@ -427,13 +438,8 @@
}
boolean chainRemoved = false;
- if (other.mChains != null) {
- if (mChains != null) {
- chainRemoved = mChains.removeAll(other.mChains);
- }
- } else if (mChains != null) {
- mChains.clear();
- chainRemoved = true;
+ if (other.mChains != null && mChains != null) {
+ chainRemoved = mChains.removeAll(other.mChains);
}
return uidRemoved || chainRemoved;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 68c242d..f4deeed 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,9 +16,6 @@
package android.os.storage;
-import static android.net.TrafficStats.GB_IN_BYTES;
-import static android.net.TrafficStats.MB_IN_BYTES;
-
import android.annotation.BytesLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -59,6 +56,7 @@
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
+import android.util.DataUnit;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -116,6 +114,8 @@
/** {@hide} */
public static final String PROP_HAS_ADOPTABLE = "vold.has_adoptable";
/** {@hide} */
+ public static final String PROP_HAS_RESERVED = "vold.has_reserved";
+ /** {@hide} */
public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
/** {@hide} */
public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
@@ -1197,12 +1197,12 @@
}
private static final int DEFAULT_THRESHOLD_PERCENTAGE = 5;
- private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
+ private static final long DEFAULT_THRESHOLD_MAX_BYTES = DataUnit.MEBIBYTES.toBytes(500);
private static final int DEFAULT_CACHE_PERCENTAGE = 10;
- private static final long DEFAULT_CACHE_MAX_BYTES = 5 * GB_IN_BYTES;
+ private static final long DEFAULT_CACHE_MAX_BYTES = DataUnit.GIBIBYTES.toBytes(5);
- private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
+ private static final long DEFAULT_FULL_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(1);
/**
* Return the number of available bytes until the given path is considered
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 99fcdad..e7fd59e 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -16,7 +16,6 @@
package android.provider;
-import static android.net.TrafficStats.KB_IN_BYTES;
import static android.system.OsConstants.SEEK_SET;
import static com.android.internal.util.Preconditions.checkArgument;
@@ -51,6 +50,7 @@
import android.os.storage.StorageVolume;
import android.system.ErrnoException;
import android.system.Os;
+import android.util.DataUnit;
import android.util.Log;
import libcore.io.IoUtils;
@@ -173,7 +173,7 @@
/**
* Buffer is large enough to rewind past any EXIF headers.
*/
- private static final int THUMBNAIL_BUFFER_SIZE = (int) (128 * KB_IN_BYTES);
+ private static final int THUMBNAIL_BUFFER_SIZE = (int) DataUnit.KIBIBYTES.toBytes(128);
/** {@hide} */
public static final String EXTERNAL_STORAGE_PROVIDER_AUTHORITY =
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 009fc39..66d1bba 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7191,13 +7191,6 @@
public static final String QS_TILES = "sysui_qs_tiles";
/**
- * Whether preloaded APKs have been installed for the user.
- * @hide
- */
- public static final String DEMO_USER_SETUP_COMPLETE
- = "demo_user_setup_complete";
-
- /**
* Specifies whether the web action API is enabled.
*
* @hide
@@ -8711,6 +8704,8 @@
/**
* Whether soft AP will shut down after a timeout period when no devices are connected.
+ *
+ * Type: int (0 for false, 1 for true)
* @hide
*/
public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
@@ -9782,6 +9777,22 @@
public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants";
/**
+ * BatteryStats specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex: "foo=1,bar=true"
+ *
+ * The following keys are supported:
+ * <pre>
+ * track_cpu_times_by_proc_state (boolean)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * see also com.android.internal.os.BatteryStatsImpl.Constants
+ */
+ public static final String BATTERY_STATS_CONSTANTS = "battery_stats_constants";
+
+ /**
* Whether or not App Standby feature is enabled. This controls throttling of apps
* based on usage patterns and predictions.
* Type: int (0 for false, 1 for true)
@@ -9791,6 +9802,22 @@
public static final java.lang.String APP_STANDBY_ENABLED = "app_standby_enabled";
/**
+ * Feature flag to enable or disable the Forced App Standby feature.
+ * Type: int (0 for false, 1 for true)
+ * Default: 1
+ * @hide
+ */
+ public static final String FORCED_APP_STANDBY_ENABLED = "forced_app_standby_enabled";
+
+ /**
+ * Whether or not Network Watchlist feature is enabled.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 6a3c55e..70de9ee 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -172,6 +172,11 @@
*/
public static final String DURATION = Calls.DURATION;
/**
+ * Whether or not the voicemail has been acknowledged (notification sent to the user).
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String NEW = Calls.NEW;
+ /**
* Whether this item has been read or otherwise consumed by the user.
* <P>Type: INTEGER (boolean)</P>
*/
diff --git a/core/java/android/security/recoverablekeystore/KeyDerivationParameters.java b/core/java/android/security/recoverablekeystore/KeyDerivationParameters.java
index 978e60e..d162455 100644
--- a/core/java/android/security/recoverablekeystore/KeyDerivationParameters.java
+++ b/core/java/android/security/recoverablekeystore/KeyDerivationParameters.java
@@ -60,7 +60,7 @@
/**
* Creates instance of the class to to derive key using salted SHA256 hash.
*/
- public static KeyDerivationParameters createSHA256Parameters(@NonNull byte[] salt) {
+ public static KeyDerivationParameters createSha256Parameters(@NonNull byte[] salt) {
return new KeyDerivationParameters(ALGORITHM_SHA256, salt);
}
diff --git a/core/java/android/security/recoverablekeystore/KeyEntryRecoveryData.java b/core/java/android/security/recoverablekeystore/KeyEntryRecoveryData.java
index 80f5aa7..5f56c91 100644
--- a/core/java/android/security/recoverablekeystore/KeyEntryRecoveryData.java
+++ b/core/java/android/security/recoverablekeystore/KeyEntryRecoveryData.java
@@ -22,13 +22,12 @@
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.
+ * <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
@@ -37,49 +36,48 @@
* @hide
*/
public final class KeyEntryRecoveryData implements Parcelable {
- private final byte[] mAlias;
+ private final String mAlias;
// The only supported format is AES-256 symmetric key.
private final byte[] mEncryptedKeyMaterial;
- public KeyEntryRecoveryData(@NonNull byte[] alias, @NonNull byte[] encryptedKeyMaterial) {
+ public KeyEntryRecoveryData(@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 byte[] getAlias() {
+ public @NonNull String getAlias() {
return mAlias;
}
- /**
- * Encrypted key material encrypted by recovery key.
- */
+ /** Encrypted key material encrypted by recovery key. */
public @NonNull byte[] getEncryptedKeyMaterial() {
return mEncryptedKeyMaterial;
}
public static final Parcelable.Creator<KeyEntryRecoveryData> CREATOR =
new Parcelable.Creator<KeyEntryRecoveryData>() {
- public KeyEntryRecoveryData createFromParcel(Parcel in) {
- return new KeyEntryRecoveryData(in);
- }
+ public KeyEntryRecoveryData createFromParcel(Parcel in) {
+ return new KeyEntryRecoveryData(in);
+ }
- public KeyEntryRecoveryData[] newArray(int length) {
- return new KeyEntryRecoveryData[length];
- }
- };
+ public KeyEntryRecoveryData[] newArray(int length) {
+ return new KeyEntryRecoveryData[length];
+ }
+ };
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeByteArray(mAlias);
+ out.writeString(mAlias);
out.writeByteArray(mEncryptedKeyMaterial);
}
protected KeyEntryRecoveryData(Parcel in) {
- mAlias = in.createByteArray();
+ mAlias = in.readString();
mEncryptedKeyMaterial = in.createByteArray();
}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
index 0412326..a65330c 100644
--- a/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
@@ -43,18 +43,61 @@
public static final int NO_ERROR = KeyStore.NO_ERROR;
public static final int SYSTEM_ERROR = KeyStore.SYSTEM_ERROR;
+
+ /**
+ * Failed because the loader has not been initialized with a recovery public key yet.
+ */
public static final int ERROR_UNINITIALIZED_RECOVERY_PUBLIC_KEY = 20;
+
+ /**
+ * Failed because no snapshot is yet pending to be synced for the user.
+ */
public static final int ERROR_NO_SNAPSHOT_PENDING = 21;
+
+ /**
+ * Failed due to an error internal to AndroidKeyStore.
+ */
public static final int ERROR_KEYSTORE_INTERNAL_ERROR = 22;
+
+ /**
+ * Failed because the user does not have a lock screen set.
+ */
public static final int ERROR_INSECURE_USER = 24;
/**
+ * Failed because of an internal database error.
+ */
+ public static final int ERROR_DATABASE_ERROR = 25;
+
+ /**
+ * Failed because the provided certificate was not a valid X509 certificate.
+ */
+ public static final int ERROR_BAD_X509_CERTIFICATE = 26;
+
+ /**
+ * Should never be thrown - some algorithm that all AOSP implementations must support is
+ * not available.
+ */
+ public static final int ERROR_UNEXPECTED_MISSING_ALGORITHM = 27;
+
+ /**
+ * The caller is attempting to perform an operation that is not yet fully supported in the API.
+ */
+ public static final int ERROR_NOT_YET_SUPPORTED = 28;
+
+ /**
+ * 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.
+ */
+ public static final int ERROR_DECRYPTION_FAILED = 29;
+
+ /**
* Rate limit is enforced to prevent using too many trusted remote devices, since each device
* can have its own number of user secret guesses allowed.
*
* @hide
*/
- public static final int RATE_LIMIT_EXCEEDED = 21;
+ public static final int ERROR_RATE_LIMIT_EXCEEDED = 30;
/** Key has been successfully synced. */
public static final int RECOVERY_STATUS_SYNCED = 0;
@@ -89,12 +132,13 @@
/**
* Creates new {@link #RecoverableKeyStoreLoaderException} instance from the error code.
*
- * @param errorCode
+ * @param errorCode An error code, as listed at the top of this file.
+ * @param message The associated error message.
* @hide
*/
- public static RecoverableKeyStoreLoaderException fromErrorCode(int errorCode) {
- return new RecoverableKeyStoreLoaderException(
- errorCode, getMessageFromErrorCode(errorCode));
+ public static RecoverableKeyStoreLoaderException fromErrorCode(
+ int errorCode, String message) {
+ return new RecoverableKeyStoreLoaderException(errorCode, message);
}
/**
@@ -106,33 +150,18 @@
*/
static RecoverableKeyStoreLoaderException fromServiceSpecificException(
ServiceSpecificException e) throws RecoverableKeyStoreLoaderException {
- throw RecoverableKeyStoreLoaderException.fromErrorCode(e.errorCode);
+ throw RecoverableKeyStoreLoaderException.fromErrorCode(e.errorCode, e.getMessage());
}
private RecoverableKeyStoreLoaderException(int errorCode, String message) {
super(message);
+ mErrorCode = errorCode;
}
/** Returns errorCode. */
public int getErrorCode() {
return mErrorCode;
}
-
- /** @hide */
- private static String getMessageFromErrorCode(int errorCode) {
- switch (errorCode) {
- case NO_ERROR:
- return "OK";
- case SYSTEM_ERROR:
- return "System error";
- case ERROR_UNINITIALIZED_RECOVERY_PUBLIC_KEY:
- return "Recovery service is not initialized";
- case RATE_LIMIT_EXCEEDED:
- return "Rate limit exceeded";
- default:
- return String.valueOf("Unknown error code " + errorCode);
- }
- }
}
/**
@@ -449,10 +478,12 @@
* 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 RecoverableKeyStoreLoaderException if an error occurred generating and storing the
* key.
*/
- public byte[] generateAndStoreKey(String alias) throws RecoverableKeyStoreLoaderException {
+ public byte[] generateAndStoreKey(@NonNull String alias)
+ throws RecoverableKeyStoreLoaderException {
try {
return mBinder.generateAndStoreKey(alias);
} catch (RemoteException e) {
@@ -461,4 +492,19 @@
throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
}
}
+
+ /**
+ * Removes a key called {@code alias} from the recoverable key store.
+ *
+ * @param alias The key alias.
+ */
+ public void removeKey(@NonNull String alias) throws RecoverableKeyStoreLoaderException {
+ try {
+ mBinder.removeKey(alias);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ }
+ }
}
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index b47e872..09bba4b 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -16,9 +16,14 @@
package android.service.carrier;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telephony.uicc.IccUtils;
+
+import java.util.Objects;
+
/**
* Used to pass info to CarrierConfigService implementations so they can decide what values to
* return.
@@ -40,13 +45,13 @@
private String mMcc;
private String mMnc;
- private String mSpn;
- private String mImsi;
- private String mGid1;
- private String mGid2;
+ private @Nullable String mSpn;
+ private @Nullable String mImsi;
+ private @Nullable String mGid1;
+ private @Nullable String mGid2;
- public CarrierIdentifier(String mcc, String mnc, String spn, String imsi, String gid1,
- String gid2) {
+ public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
+ @Nullable String gid1, @Nullable String gid2) {
mMcc = mcc;
mMnc = mnc;
mSpn = spn;
@@ -55,6 +60,32 @@
mGid2 = gid2;
}
+ /**
+ * Creates a carrier identifier instance.
+ *
+ * @param mccMnc A 3-byte array as defined by 3GPP TS 24.008.
+ * @param gid1 The group identifier level 1.
+ * @param gid2 The group identifier level 2.
+ * @throws IllegalArgumentException If the length of {@code mccMnc} is not 3.
+ */
+ public CarrierIdentifier(byte[] mccMnc, @Nullable String gid1, @Nullable String gid2) {
+ if (mccMnc.length != 3) {
+ throw new IllegalArgumentException(
+ "MCC & MNC must be set by a 3-byte array: byte[" + mccMnc.length + "]");
+ }
+ String hex = IccUtils.bytesToHexString(mccMnc);
+ mMcc = new String(new char[] {hex.charAt(1), hex.charAt(0), hex.charAt(3)});
+ if (hex.charAt(2) == 'F') {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4)});
+ } else {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4), hex.charAt(2)});
+ }
+ mGid1 = gid1;
+ mGid2 = gid2;
+ mSpn = null;
+ mImsi = null;
+ }
+
/** @hide */
public CarrierIdentifier(Parcel parcel) {
readFromParcel(parcel);
@@ -71,26 +102,60 @@
}
/** Get the service provider name. */
+ @Nullable
public String getSpn() {
return mSpn;
}
/** Get the international mobile subscriber identity. */
+ @Nullable
public String getImsi() {
return mImsi;
}
/** Get the group identifier level 1. */
+ @Nullable
public String getGid1() {
return mGid1;
}
/** Get the group identifier level 2. */
+ @Nullable
public String getGid2() {
return mGid2;
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ CarrierIdentifier that = (CarrierIdentifier) obj;
+ return Objects.equals(mMcc, that.mMcc)
+ && Objects.equals(mMnc, that.mMnc)
+ && Objects.equals(mSpn, that.mSpn)
+ && Objects.equals(mImsi, that.mImsi)
+ && Objects.equals(mGid1, that.mGid1)
+ && Objects.equals(mGid2, that.mGid2);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(mMcc);
+ result = 31 * result + Objects.hashCode(mMnc);
+ result = 31 * result + Objects.hashCode(mSpn);
+ result = 31 * result + Objects.hashCode(mImsi);
+ result = 31 * result + Objects.hashCode(mGid1);
+ result = 31 * result + Objects.hashCode(mGid2);
+ return result;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index ba6c9a2..8e752d1 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -15,12 +15,19 @@
*/
package android.service.euicc;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
import android.telephony.UiccAccessRule;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Information about an embedded profile (subscription) on an eUICC.
*
@@ -30,18 +37,90 @@
*/
public final class EuiccProfileInfo implements Parcelable {
+ /** Profile policy rules (bit mask) */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "POLICY_RULE_" }, value = {
+ POLICY_RULE_DO_NOT_DISABLE,
+ POLICY_RULE_DO_NOT_DELETE,
+ POLICY_RULE_DELETE_AFTER_DISABLING
+ })
+ public @interface PolicyRule {}
+ /** Once this profile is enabled, it cannot be disabled. */
+ public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
+ /** This profile cannot be deleted. */
+ public static final int POLICY_RULE_DO_NOT_DELETE = 1 << 1;
+ /** This profile should be deleted after being disabled. */
+ public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 1 << 2;
+
+ /** Class of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
+ PROFILE_CLASS_TESTING,
+ PROFILE_CLASS_PROVISIONING,
+ PROFILE_CLASS_OPERATIONAL,
+ PROFILE_CLASS_UNSET
+ })
+ public @interface ProfileClass {}
+ /** Testing profiles */
+ public static final int PROFILE_CLASS_TESTING = 0;
+ /** Provisioning profiles which are pre-loaded on eUICC */
+ public static final int PROFILE_CLASS_PROVISIONING = 1;
+ /** Operational profiles which can be pre-loaded or downloaded */
+ public static final int PROFILE_CLASS_OPERATIONAL = 2;
+ /**
+ * Profile class not set.
+ * @hide
+ */
+ public static final int PROFILE_CLASS_UNSET = -1;
+
+ /** State of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_STATE_" }, value = {
+ PROFILE_STATE_DISABLED,
+ PROFILE_STATE_ENABLED,
+ PROFILE_STATE_UNSET
+ })
+ public @interface ProfileState {}
+ /** Disabled profiles */
+ public static final int PROFILE_STATE_DISABLED = 0;
+ /** Enabled profile */
+ public static final int PROFILE_STATE_ENABLED = 1;
+ /**
+ * Profile state not set.
+ * @hide
+ */
+ public static final int PROFILE_STATE_UNSET = -1;
+
/** The iccid of the subscription. */
public final String iccid;
+ /** An optional nickname for the subscription. */
+ public final @Nullable String nickname;
+
+ /** The service provider name for the subscription. */
+ public final String serviceProviderName;
+
+ /** The profile name for the subscription. */
+ public final String profileName;
+
+ /** Profile class for the subscription. */
+ @ProfileClass public final int profileClass;
+
+ /** The profile state of the subscription. */
+ @ProfileState public final int state;
+
+ /** The operator Id of the subscription. */
+ public final CarrierIdentifier carrierIdentifier;
+
+ /** The policy rules of the subscription. */
+ @PolicyRule public final int policyRules;
+
/**
* Optional access rules defining which apps can manage this subscription. If unset, only the
* platform can manage it.
*/
public final @Nullable UiccAccessRule[] accessRules;
- /** An optional nickname for the subscription. */
- public final @Nullable String nickname;
-
public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
@Override
public EuiccProfileInfo createFromParcel(Parcel in) {
@@ -54,6 +133,12 @@
}
};
+ // TODO(b/70292228): Remove this method when LPA can be updated.
+ /**
+ * @hide
+ * @deprecated - Do not use.
+ */
+ @Deprecated
public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
@Nullable String nickname) {
if (!TextUtils.isDigitsOnly(iccid)) {
@@ -62,23 +147,290 @@
this.iccid = iccid;
this.accessRules = accessRules;
this.nickname = nickname;
+
+ this.serviceProviderName = null;
+ this.profileName = null;
+ this.profileClass = PROFILE_CLASS_UNSET;
+ this.state = PROFILE_CLASS_UNSET;
+ this.carrierIdentifier = null;
+ this.policyRules = 0;
}
private EuiccProfileInfo(Parcel in) {
iccid = in.readString();
- accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
nickname = in.readString();
+ serviceProviderName = in.readString();
+ profileName = in.readString();
+ profileClass = in.readInt();
+ state = in.readInt();
+ byte exist = in.readByte();
+ if (exist == (byte) 1) {
+ carrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
+ } else {
+ carrierIdentifier = null;
+ }
+ policyRules = in.readInt();
+ accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(iccid);
- dest.writeTypedArray(accessRules, flags);
dest.writeString(nickname);
+ dest.writeString(serviceProviderName);
+ dest.writeString(profileName);
+ dest.writeInt(profileClass);
+ dest.writeInt(state);
+ if (carrierIdentifier != null) {
+ dest.writeByte((byte) 1);
+ carrierIdentifier.writeToParcel(dest, flags);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ dest.writeInt(policyRules);
+ dest.writeTypedArray(accessRules, flags);
}
@Override
public int describeContents() {
return 0;
}
+
+ /** The builder to build a new {@link EuiccProfileInfo} instance. */
+ public static final class Builder {
+ public String iccid;
+ public UiccAccessRule[] accessRules;
+ public String nickname;
+ public String serviceProviderName;
+ public String profileName;
+ @ProfileClass public int profileClass;
+ @ProfileState public int state;
+ public CarrierIdentifier carrierIdentifier;
+ @PolicyRule public int policyRules;
+
+ public Builder() {}
+
+ public Builder(EuiccProfileInfo baseProfile) {
+ iccid = baseProfile.iccid;
+ nickname = baseProfile.nickname;
+ serviceProviderName = baseProfile.serviceProviderName;
+ profileName = baseProfile.profileName;
+ profileClass = baseProfile.profileClass;
+ state = baseProfile.state;
+ carrierIdentifier = baseProfile.carrierIdentifier;
+ policyRules = baseProfile.policyRules;
+ accessRules = baseProfile.accessRules;
+ }
+
+ /** Builds the profile instance. */
+ public EuiccProfileInfo build() {
+ if (iccid == null) {
+ throw new IllegalStateException("ICCID must be set for a profile.");
+ }
+ return new EuiccProfileInfo(
+ iccid,
+ nickname,
+ serviceProviderName,
+ profileName,
+ profileClass,
+ state,
+ carrierIdentifier,
+ policyRules,
+ accessRules);
+ }
+
+ /** Sets the iccId of the subscription. */
+ public Builder setIccid(String value) {
+ if (!TextUtils.isDigitsOnly(value)) {
+ throw new IllegalArgumentException("iccid contains invalid characters: " + value);
+ }
+ iccid = value;
+ return this;
+ }
+
+ /** Sets the nickname of the subscription. */
+ public Builder setNickname(String value) {
+ nickname = value;
+ return this;
+ }
+
+ /** Sets the service provider name of the subscription. */
+ public Builder setServiceProviderName(String value) {
+ serviceProviderName = value;
+ return this;
+ }
+
+ /** Sets the profile name of the subscription. */
+ public Builder setProfileName(String value) {
+ profileName = value;
+ return this;
+ }
+
+ /** Sets the profile class of the subscription. */
+ public Builder setProfileClass(@ProfileClass int value) {
+ profileClass = value;
+ return this;
+ }
+
+ /** Sets the state of the subscription. */
+ public Builder setState(@ProfileState int value) {
+ state = value;
+ return this;
+ }
+
+ /** Sets the carrier identifier of the subscription. */
+ public Builder setCarrierIdentifier(CarrierIdentifier value) {
+ carrierIdentifier = value;
+ return this;
+ }
+
+ /** Sets the policy rules of the subscription. */
+ public Builder setPolicyRules(@PolicyRule int value) {
+ policyRules = value;
+ return this;
+ }
+
+ /** Sets the access rules of the subscription. */
+ public Builder setUiccAccessRule(@Nullable UiccAccessRule[] value) {
+ accessRules = value;
+ return this;
+ }
+ }
+
+ private EuiccProfileInfo(
+ String iccid,
+ @Nullable String nickname,
+ String serviceProviderName,
+ String profileName,
+ @ProfileClass int profileClass,
+ @ProfileState int state,
+ CarrierIdentifier carrierIdentifier,
+ @PolicyRule int policyRules,
+ @Nullable UiccAccessRule[] accessRules) {
+ this.iccid = iccid;
+ this.nickname = nickname;
+ this.serviceProviderName = serviceProviderName;
+ this.profileName = profileName;
+ this.profileClass = profileClass;
+ this.state = state;
+ this.carrierIdentifier = carrierIdentifier;
+ this.policyRules = policyRules;
+ this.accessRules = accessRules;
+ }
+
+ /** Gets the ICCID string. */
+ public String getIccid() {
+ return iccid;
+ }
+
+ /** Gets the access rules. */
+ @Nullable
+ public UiccAccessRule[] getUiccAccessRules() {
+ return accessRules;
+ }
+
+ /** Gets the nickname. */
+ public String getNickname() {
+ return nickname;
+ }
+
+ /** Gets the service provider name. */
+ public String getServiceProviderName() {
+ return serviceProviderName;
+ }
+
+ /** Gets the profile name. */
+ public String getProfileName() {
+ return profileName;
+ }
+
+ /** Gets the profile class. */
+ @ProfileClass
+ public int getProfileClass() {
+ return profileClass;
+ }
+
+ /** Gets the state of the subscription. */
+ @ProfileState
+ public int getState() {
+ return state;
+ }
+
+ /** Gets the carrier identifier. */
+ public CarrierIdentifier getCarrierIdentifier() {
+ return carrierIdentifier;
+ }
+
+ /** Gets the policy rules. */
+ @PolicyRule
+ public int getPolicyRules() {
+ return policyRules;
+ }
+
+ /** Returns whether any policy rule exists. */
+ public boolean hasPolicyRules() {
+ return policyRules != 0;
+ }
+
+ /** Checks whether a certain policy rule exists. */
+ public boolean hasPolicyRule(@PolicyRule int policy) {
+ return (policyRules & policy) != 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccProfileInfo that = (EuiccProfileInfo) obj;
+ return Objects.equals(iccid, that.iccid)
+ && Objects.equals(nickname, that.nickname)
+ && Objects.equals(serviceProviderName, that.serviceProviderName)
+ && Objects.equals(profileName, that.profileName)
+ && profileClass == that.profileClass
+ && state == that.state
+ && Objects.equals(carrierIdentifier, that.carrierIdentifier)
+ && policyRules == that.policyRules
+ && Arrays.equals(accessRules, that.accessRules);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(iccid);
+ result = 31 * result + Objects.hashCode(nickname);
+ result = 31 * result + Objects.hashCode(serviceProviderName);
+ result = 31 * result + Objects.hashCode(profileName);
+ result = 31 * result + profileClass;
+ result = 31 * result + state;
+ result = 31 * result + Objects.hashCode(carrierIdentifier);
+ result = 31 * result + policyRules;
+ result = 31 * result + Arrays.hashCode(accessRules);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "EuiccProfileInfo (nickname="
+ + nickname
+ + ", serviceProviderName="
+ + serviceProviderName
+ + ", profileName="
+ + profileName
+ + ", profileClass="
+ + profileClass
+ + ", state="
+ + state
+ + ", CarrierIdentifier="
+ + carrierIdentifier.toString()
+ + ", policyRules="
+ + policyRules
+ + ", accessRules="
+ + Arrays.toString(accessRules)
+ + ")";
+ }
}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index fb53007..be85800 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -193,6 +193,18 @@
}
/**
+ * Callback class for {@link #onStartOtaIfNecessary(int, OtaStatusChangedCallback)}
+ *
+ * The status of OTA which can be {@code android.telephony.euicc.EuiccManager#EUICC_OTA_}
+ *
+ * @see IEuiccService#startOtaIfNecessary
+ */
+ public interface OtaStatusChangedCallback {
+ /** Called when OTA status is changed. */
+ void onOtaStatusChanged(int status);
+ }
+
+ /**
* Return the EID of the eUICC.
*
* @param slotId ID of the SIM slot being queried. This is currently not populated but is here
@@ -214,6 +226,16 @@
public abstract @OtaStatus int onGetOtaStatus(int slotId);
/**
+ * Perform OTA if current OS is not the latest one.
+ *
+ * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
+ * but is here to future-proof the APIs.
+ * @param statusChangedCallback Function called when OTA status changed.
+ */
+ public abstract void onStartOtaIfNecessary(
+ int slotId, OtaStatusChangedCallback statusChangedCallback);
+
+ /**
* Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
*
* @param slotId ID of the SIM slot to use for the operation. This is currently not populated
@@ -396,6 +418,26 @@
}
@Override
+ public void startOtaIfNecessary(
+ int slotId, IOtaStatusChangedCallback statusChangedCallback) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ EuiccService.this.onStartOtaIfNecessary(slotId, new OtaStatusChangedCallback() {
+ @Override
+ public void onOtaStatusChanged(int status) {
+ try {
+ statusChangedCallback.onOtaStatusChanged(status);
+ } catch (RemoteException e) {
+ // Can't communicate with the phone process; ignore.
+ }
+ }
+ });
+ }
+ });
+ }
+
+ @Override
public void getOtaStatus(int slotId, IGetOtaStatusCallback callback) {
mExecutor.execute(new Runnable() {
@Override
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index a24e5c3..45be527 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -25,6 +25,7 @@
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IGetOtaStatusCallback;
+import android.service.euicc.IOtaStatusChangedCallback;
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
@@ -39,6 +40,7 @@
boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
void getEid(int slotId, in IGetEidCallback callback);
void getOtaStatus(int slotId, in IGetOtaStatusCallback callback);
+ void startOtaIfNecessary(int slotId, in IOtaStatusChangedCallback statusChangedCallback);
void getEuiccProfileInfoList(int slotId, in IGetEuiccProfileInfoListCallback callback);
void getDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim,
in IGetDefaultDownloadableSubscriptionListCallback callback);
diff --git a/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
new file mode 100644
index 0000000..caec75f
--- /dev/null
+++ b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.service.euicc;
+
+/** @hide */
+oneway interface IOtaStatusChangedCallback {
+ void onOtaStatusChanged(int status);
+}
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 18d4a1e..20cd906 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -890,6 +890,8 @@
createLegacyIconExtras(notification);
// populate remote views for older clients.
maybePopulateRemoteViews(notification);
+ // populate people for older clients.
+ maybePopulatePeople(notification);
} catch (IllegalArgumentException e) {
if (corruptNotifications == null) {
corruptNotifications = new ArrayList<>(N);
@@ -1178,6 +1180,25 @@
}
}
+ /**
+ * Populates remote views for pre-P targeting apps.
+ */
+ private void maybePopulatePeople(Notification notification) {
+ if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P) {
+ ArrayList<Notification.Person> people = notification.extras.getParcelableArrayList(
+ Notification.EXTRA_PEOPLE_LIST);
+ if (people != null && people.isEmpty()) {
+ int size = people.size();
+ String[] peopleArray = new String[size];
+ for (int i = 0; i < size; i++) {
+ Notification.Person person = people.get(i);
+ peopleArray[i] = person.resolveToLegacyUri();
+ }
+ notification.extras.putStringArray(Notification.EXTRA_PEOPLE, peopleArray);
+ }
+ }
+ }
+
/** @hide */
protected class NotificationListenerWrapper extends INotificationListener.Stub {
@Override
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 6bca37a..18431ca 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -1096,6 +1096,11 @@
public void onSpanChanged(Spannable s, Object o, int start, int end, int nstart, int nend) {
if (o instanceof UpdateLayout) {
+ if (start > end) {
+ // Bug: 67926915 start cannot be determined, fallback to reflow from start
+ // instead of causing an exception
+ start = 0;
+ }
reflow(s, start, end - start, end - start);
reflow(s, nstart, nend - nstart, nend - nstart);
}
diff --git a/core/java/android/util/DataUnit.java b/core/java/android/util/DataUnit.java
new file mode 100644
index 0000000..3cc1bd8
--- /dev/null
+++ b/core/java/android/util/DataUnit.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.time.temporal.ChronoUnit;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Constants for common byte-related units. Note that both SI and IEC units are
+ * supported, and you'll need to pick the correct one for your use-case.
+ * <p>
+ * This design is mirrored after {@link TimeUnit} and {@link ChronoUnit}.
+ *
+ * @hide
+ */
+public enum DataUnit {
+ KILOBYTES { @Override public long toBytes(long v) { return v * 1_000; } },
+ MEGABYTES { @Override public long toBytes(long v) { return v * 1_000_000; } },
+ GIGABYTES { @Override public long toBytes(long v) { return v * 1_000_000_000; } },
+ KIBIBYTES { @Override public long toBytes(long v) { return v * 1_024; } },
+ MEBIBYTES { @Override public long toBytes(long v) { return v * 1_048_576; } },
+ GIBIBYTES { @Override public long toBytes(long v) { return v * 1_073_741_824; } };
+
+ public long toBytes(long v) {
+ throw new AbstractMethodError();
+ }
+}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index d31bc1f..1d5392e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -43,7 +43,7 @@
DEFAULT_FLAGS.put("settings_connected_device_v2", "true");
DEFAULT_FLAGS.put("settings_battery_v2", "false");
DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
- DEFAULT_FLAGS.put("settings_security_settings_v2", "false");
+ DEFAULT_FLAGS.put("settings_security_settings_v2", "true");
}
/**
diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java
index 0a00794..7eef63e 100644
--- a/core/java/android/util/KeyValueListParser.java
+++ b/core/java/android/util/KeyValueListParser.java
@@ -17,6 +17,9 @@
import android.text.TextUtils;
+import java.time.Duration;
+import java.time.format.DateTimeParseException;
+
/**
* Parses a list of key=value pairs, separated by some delimiter, and puts the results in
* an internal Map. Values can be then queried by key, or if not found, a default value
@@ -189,4 +192,24 @@
public String keyAt(int index) {
return mValues.keyAt(index);
}
+
+ /**
+ * {@hide}
+ * Parse a duration in millis based on java.time.Duration or just a number (millis)
+ */
+ public long getDurationMillis(String key, long def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ try {
+ if (value.startsWith("P") || value.startsWith("p")) {
+ return Duration.parse(value).toMillis();
+ } else {
+ return Long.parseLong(value);
+ }
+ } catch (NumberFormatException | DateTimeParseException e) {
+ // fallthrough
+ }
+ }
+ return def;
+ }
}
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 530937e..ce8998f 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -23,6 +23,9 @@
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512;
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PSS_WITH_SHA256;
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PSS_WITH_SHA512;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_DSA_WITH_SHA256;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_ECDSA_WITH_SHA256;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256;
import static android.util.apk.ApkSigningBlockUtils.compareSignatureAlgorithm;
import static android.util.apk.ApkSigningBlockUtils.getContentDigestAlgorithmJcaDigestAlgorithm;
import static android.util.apk.ApkSigningBlockUtils.getLengthPrefixedSlice;
@@ -35,7 +38,6 @@
import android.util.Pair;
import java.io.ByteArrayInputStream;
-import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException;
@@ -139,7 +141,7 @@
private static X509Certificate[][] verify(RandomAccessFile apk, boolean verifyIntegrity)
throws SignatureNotFoundException, SecurityException, IOException {
SignatureInfo signatureInfo = findSignature(apk);
- return verify(apk.getFD(), signatureInfo, verifyIntegrity);
+ return verify(apk, signatureInfo, verifyIntegrity);
}
/**
@@ -162,9 +164,9 @@
* against the APK file.
*/
private static X509Certificate[][] verify(
- FileDescriptor apkFileDescriptor,
+ RandomAccessFile apk,
SignatureInfo signatureInfo,
- boolean doVerifyIntegrity) throws SecurityException {
+ boolean doVerifyIntegrity) throws SecurityException, IOException {
int signerCount = 0;
Map<Integer, byte[]> contentDigests = new ArrayMap<>();
List<X509Certificate[]> signerCerts = new ArrayList<>();
@@ -202,13 +204,7 @@
}
if (doVerifyIntegrity) {
- ApkSigningBlockUtils.verifyIntegrity(
- contentDigests,
- apkFileDescriptor,
- signatureInfo.apkSigningBlockOffset,
- signatureInfo.centralDirOffset,
- signatureInfo.eocdOffset,
- signatureInfo.eocd);
+ ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
}
return signerCerts.toArray(new X509Certificate[signerCerts.size()][]);
@@ -386,6 +382,7 @@
}
return;
}
+
private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
switch (sigAlgorithm) {
case SIGNATURE_RSA_PSS_WITH_SHA256:
@@ -395,6 +392,9 @@
case SIGNATURE_ECDSA_WITH_SHA256:
case SIGNATURE_ECDSA_WITH_SHA512:
case SIGNATURE_DSA_WITH_SHA256:
+ case SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256:
+ case SIGNATURE_VERITY_ECDSA_WITH_SHA256:
+ case SIGNATURE_VERITY_DSA_WITH_SHA256:
return true;
default:
return false;
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index e43dee3..c9e67fe 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -23,6 +23,9 @@
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512;
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PSS_WITH_SHA256;
import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_RSA_PSS_WITH_SHA512;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_DSA_WITH_SHA256;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_ECDSA_WITH_SHA256;
+import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256;
import static android.util.apk.ApkSigningBlockUtils.compareSignatureAlgorithm;
import static android.util.apk.ApkSigningBlockUtils.getContentDigestAlgorithmJcaDigestAlgorithm;
import static android.util.apk.ApkSigningBlockUtils.getLengthPrefixedSlice;
@@ -36,7 +39,6 @@
import android.util.Pair;
import java.io.ByteArrayInputStream;
-import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException;
@@ -136,7 +138,7 @@
private static VerifiedSigner verify(RandomAccessFile apk, boolean verifyIntegrity)
throws SignatureNotFoundException, SecurityException, IOException {
SignatureInfo signatureInfo = findSignature(apk);
- return verify(apk.getFD(), signatureInfo, verifyIntegrity);
+ return verify(apk, signatureInfo, verifyIntegrity);
}
/**
@@ -159,7 +161,7 @@
* against the APK file.
*/
private static VerifiedSigner verify(
- FileDescriptor apkFileDescriptor,
+ RandomAccessFile apk,
SignatureInfo signatureInfo,
boolean doVerifyIntegrity) throws SecurityException {
int signerCount = 0;
@@ -206,13 +208,7 @@
}
if (doVerifyIntegrity) {
- ApkSigningBlockUtils.verifyIntegrity(
- contentDigests,
- apkFileDescriptor,
- signatureInfo.apkSigningBlockOffset,
- signatureInfo.centralDirOffset,
- signatureInfo.eocdOffset,
- signatureInfo.eocd);
+ ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
}
return result;
@@ -512,6 +508,9 @@
case SIGNATURE_ECDSA_WITH_SHA256:
case SIGNATURE_ECDSA_WITH_SHA512:
case SIGNATURE_DSA_WITH_SHA256:
+ case SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256:
+ case SIGNATURE_VERITY_ECDSA_WITH_SHA256:
+ case SIGNATURE_VERITY_DSA_WITH_SHA256:
return true;
default:
return false;
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 9279510..9d53847 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -16,6 +16,7 @@
package android.util.apk;
+import android.util.ArrayMap;
import android.util.Pair;
import java.io.FileDescriptor;
@@ -30,6 +31,7 @@
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
+import java.util.Arrays;
import java.util.Map;
/**
@@ -84,16 +86,41 @@
static void verifyIntegrity(
Map<Integer, byte[]> expectedDigests,
- FileDescriptor apkFileDescriptor,
- long apkSigningBlockOffset,
- long centralDirOffset,
- long eocdOffset,
- ByteBuffer eocdBuf) throws SecurityException {
-
+ RandomAccessFile apk,
+ SignatureInfo signatureInfo) throws SecurityException {
if (expectedDigests.isEmpty()) {
throw new SecurityException("No digests provided");
}
+ Map<Integer, byte[]> expected1MbChunkDigests = new ArrayMap<>();
+ if (expectedDigests.containsKey(CONTENT_DIGEST_CHUNKED_SHA256)) {
+ expected1MbChunkDigests.put(CONTENT_DIGEST_CHUNKED_SHA256,
+ expectedDigests.get(CONTENT_DIGEST_CHUNKED_SHA256));
+ }
+ if (expectedDigests.containsKey(CONTENT_DIGEST_CHUNKED_SHA512)) {
+ expected1MbChunkDigests.put(CONTENT_DIGEST_CHUNKED_SHA512,
+ expectedDigests.get(CONTENT_DIGEST_CHUNKED_SHA512));
+ }
+
+ if (expectedDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+ verifyIntegrityForVerityBasedAlgorithm(
+ expectedDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256), apk, signatureInfo);
+ } else if (!expected1MbChunkDigests.isEmpty()) {
+ try {
+ verifyIntegrityFor1MbChunkBasedAlgorithm(expected1MbChunkDigests, apk.getFD(),
+ signatureInfo);
+ } catch (IOException e) {
+ throw new SecurityException("Cannot get FD", e);
+ }
+ } else {
+ throw new SecurityException("No known digest exists for integrity check");
+ }
+ }
+
+ private static void verifyIntegrityFor1MbChunkBasedAlgorithm(
+ Map<Integer, byte[]> expectedDigests,
+ FileDescriptor apkFileDescriptor,
+ SignatureInfo signatureInfo) throws SecurityException {
// We need to verify the integrity of the following three sections of the file:
// 1. Everything up to the start of the APK Signing Block.
// 2. ZIP Central Directory.
@@ -105,16 +132,18 @@
// APK are already there in the OS's page cache and thus mmap does not use additional
// physical memory.
DataSource beforeApkSigningBlock =
- new MemoryMappedFileDataSource(apkFileDescriptor, 0, apkSigningBlockOffset);
+ new MemoryMappedFileDataSource(apkFileDescriptor, 0,
+ signatureInfo.apkSigningBlockOffset);
DataSource centralDir =
new MemoryMappedFileDataSource(
- apkFileDescriptor, centralDirOffset, eocdOffset - centralDirOffset);
+ apkFileDescriptor, signatureInfo.centralDirOffset,
+ signatureInfo.eocdOffset - signatureInfo.centralDirOffset);
// For the purposes of integrity verification, ZIP End of Central Directory's field Start of
// Central Directory must be considered to point to the offset of the APK Signing Block.
- eocdBuf = eocdBuf.duplicate();
+ ByteBuffer eocdBuf = signatureInfo.eocd.duplicate();
eocdBuf.order(ByteOrder.LITTLE_ENDIAN);
- ZipUtils.setZipEocdCentralDirectoryOffset(eocdBuf, apkSigningBlockOffset);
+ ZipUtils.setZipEocdCentralDirectoryOffset(eocdBuf, signatureInfo.apkSigningBlockOffset);
DataSource eocd = new ByteBufferDataSource(eocdBuf);
int[] digestAlgorithms = new int[expectedDigests.size()];
@@ -126,7 +155,7 @@
byte[][] actualDigests;
try {
actualDigests =
- computeContentDigests(
+ computeContentDigestsPer1MbChunk(
digestAlgorithms,
new DataSource[] {beforeApkSigningBlock, centralDir, eocd});
} catch (DigestException e) {
@@ -144,7 +173,7 @@
}
}
- private static byte[][] computeContentDigests(
+ private static byte[][] computeContentDigestsPer1MbChunk(
int[] digestAlgorithms,
DataSource[] contents) throws DigestException {
// For each digest algorithm the result is computed as follows:
@@ -256,6 +285,26 @@
return result;
}
+ private static void verifyIntegrityForVerityBasedAlgorithm(
+ byte[] expectedRootHash,
+ RandomAccessFile apk,
+ SignatureInfo signatureInfo) throws SecurityException {
+ try {
+ ApkVerityBuilder.ApkVerityResult verity = ApkVerityBuilder.generateApkVerity(apk,
+ signatureInfo, new ByteBufferFactory() {
+ @Override
+ public ByteBuffer create(int capacity) {
+ return ByteBuffer.allocate(capacity);
+ }
+ });
+ if (!Arrays.equals(expectedRootHash, verity.rootHash)) {
+ throw new SecurityException("APK verity digest of contents did not verify");
+ }
+ } catch (DigestException | IOException | NoSuchAlgorithmException e) {
+ throw new SecurityException("Error during verification", e);
+ }
+ }
+
/**
* Returns the ZIP End of Central Directory (EoCD) and its offset in the file.
*
@@ -304,9 +353,13 @@
static final int SIGNATURE_ECDSA_WITH_SHA256 = 0x0201;
static final int SIGNATURE_ECDSA_WITH_SHA512 = 0x0202;
static final int SIGNATURE_DSA_WITH_SHA256 = 0x0301;
+ static final int SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0401;
+ static final int SIGNATURE_VERITY_ECDSA_WITH_SHA256 = 0x0403;
+ static final int SIGNATURE_VERITY_DSA_WITH_SHA256 = 0x0405;
static final int CONTENT_DIGEST_CHUNKED_SHA256 = 1;
static final int CONTENT_DIGEST_CHUNKED_SHA512 = 2;
+ static final int CONTENT_DIGEST_VERITY_CHUNKED_SHA256 = 3;
static int compareSignatureAlgorithm(int sigAlgorithm1, int sigAlgorithm2) {
int digestAlgorithm1 = getSignatureAlgorithmContentDigestAlgorithm(sigAlgorithm1);
@@ -321,6 +374,7 @@
case CONTENT_DIGEST_CHUNKED_SHA256:
return 0;
case CONTENT_DIGEST_CHUNKED_SHA512:
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
return -1;
default:
throw new IllegalArgumentException(
@@ -329,6 +383,7 @@
case CONTENT_DIGEST_CHUNKED_SHA512:
switch (digestAlgorithm2) {
case CONTENT_DIGEST_CHUNKED_SHA256:
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
return 1;
case CONTENT_DIGEST_CHUNKED_SHA512:
return 0;
@@ -336,6 +391,18 @@
throw new IllegalArgumentException(
"Unknown digestAlgorithm2: " + digestAlgorithm2);
}
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
+ switch (digestAlgorithm2) {
+ case CONTENT_DIGEST_CHUNKED_SHA512:
+ return -1;
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
+ return 0;
+ case CONTENT_DIGEST_CHUNKED_SHA256:
+ return 1;
+ default:
+ throw new IllegalArgumentException(
+ "Unknown digestAlgorithm2: " + digestAlgorithm2);
+ }
default:
throw new IllegalArgumentException("Unknown digestAlgorithm1: " + digestAlgorithm1);
}
@@ -352,6 +419,10 @@
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
case SIGNATURE_ECDSA_WITH_SHA512:
return CONTENT_DIGEST_CHUNKED_SHA512;
+ case SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256:
+ case SIGNATURE_VERITY_ECDSA_WITH_SHA256:
+ case SIGNATURE_VERITY_DSA_WITH_SHA256:
+ return CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
default:
throw new IllegalArgumentException(
"Unknown signature algorithm: 0x"
@@ -362,6 +433,7 @@
static String getContentDigestAlgorithmJcaDigestAlgorithm(int digestAlgorithm) {
switch (digestAlgorithm) {
case CONTENT_DIGEST_CHUNKED_SHA256:
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
return "SHA-256";
case CONTENT_DIGEST_CHUNKED_SHA512:
return "SHA-512";
@@ -374,6 +446,7 @@
private static int getContentDigestAlgorithmOutputSizeBytes(int digestAlgorithm) {
switch (digestAlgorithm) {
case CONTENT_DIGEST_CHUNKED_SHA256:
+ case CONTENT_DIGEST_VERITY_CHUNKED_SHA256:
return 256 / 8;
case CONTENT_DIGEST_CHUNKED_SHA512:
return 512 / 8;
@@ -389,11 +462,14 @@
case SIGNATURE_RSA_PSS_WITH_SHA512:
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256:
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
+ case SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256:
return "RSA";
case SIGNATURE_ECDSA_WITH_SHA256:
case SIGNATURE_ECDSA_WITH_SHA512:
+ case SIGNATURE_VERITY_ECDSA_WITH_SHA256:
return "EC";
case SIGNATURE_DSA_WITH_SHA256:
+ case SIGNATURE_VERITY_DSA_WITH_SHA256:
return "DSA";
default:
throw new IllegalArgumentException(
@@ -416,14 +492,17 @@
new PSSParameterSpec(
"SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 512 / 8, 1));
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256:
+ case SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256:
return Pair.create("SHA256withRSA", null);
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
return Pair.create("SHA512withRSA", null);
case SIGNATURE_ECDSA_WITH_SHA256:
+ case SIGNATURE_VERITY_ECDSA_WITH_SHA256:
return Pair.create("SHA256withECDSA", null);
case SIGNATURE_ECDSA_WITH_SHA512:
return Pair.create("SHA512withECDSA", null);
case SIGNATURE_DSA_WITH_SHA256:
+ case SIGNATURE_VERITY_DSA_WITH_SHA256:
return Pair.create("SHA256withDSA", null);
default:
throw new IllegalArgumentException(
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index ba6b6cf..33fbf73 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -235,6 +235,8 @@
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
+ // b/68769804: For low FPS experiments.
+ setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}
private static float getRefreshRate() {
@@ -605,6 +607,7 @@
void setFPSDivisor(int divisor) {
if (divisor <= 0) divisor = 1;
mFPSDivisor = divisor;
+ ThreadedRenderer.setFPSDivisor(divisor);
}
void doFrame(long frameTimeNanos, int frame) {
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 3dcfd00..1ef5f09 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -153,7 +153,7 @@
@Override
public String toString() {
return "DisplayCutout{insets=" + mSafeInsets
- + " bounds=" + mBounds
+ + " boundingRect=" + getBoundingRect()
+ "}";
}
@@ -279,9 +279,7 @@
* @hide
*/
public static DisplayCutout fromBoundingPolygon(List<Point> points) {
- Region bounds = Region.obtain();
Path path = new Path();
-
path.reset();
for (int i = 0; i < points.size(); i++) {
Point point = points.get(i);
@@ -292,14 +290,24 @@
}
}
path.close();
+ return fromBounds(path);
+ }
+ /**
+ * Creates an instance from a bounding {@link Path}.
+ *
+ * @hide
+ */
+ public static DisplayCutout fromBounds(Path path) {
RectF clipRect = new RectF();
path.computeBounds(clipRect, false /* unused */);
Region clipRegion = Region.obtain();
clipRegion.set((int) clipRect.left, (int) clipRect.top,
(int) clipRect.right, (int) clipRect.bottom);
+ Region bounds = new Region();
bounds.setPath(path, clipRegion);
+ clipRegion.recycle();
return new DisplayCutout(ZERO_RECT, bounds);
}
@@ -329,12 +337,23 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- if (mInner == NO_CUTOUT) {
+ writeCutoutToParcel(mInner, out, flags);
+ }
+
+ /**
+ * Writes a DisplayCutout to a {@link Parcel}.
+ *
+ * @see #readCutoutFromParcel(Parcel)
+ */
+ public static void writeCutoutToParcel(DisplayCutout cutout, Parcel out, int flags) {
+ if (cutout == null) {
+ out.writeInt(-1);
+ } else if (cutout == NO_CUTOUT) {
out.writeInt(0);
} else {
out.writeInt(1);
- out.writeTypedObject(mInner.mSafeInsets, flags);
- out.writeTypedObject(mInner.mBounds, flags);
+ out.writeTypedObject(cutout.mSafeInsets, flags);
+ out.writeTypedObject(cutout.mBounds, flags);
}
}
@@ -345,13 +364,13 @@
* Needed for AIDL out parameters.
*/
public void readFromParcel(Parcel in) {
- mInner = readCutout(in);
+ mInner = readCutoutFromParcel(in);
}
public static final Creator<ParcelableWrapper> CREATOR = new Creator<ParcelableWrapper>() {
@Override
public ParcelableWrapper createFromParcel(Parcel in) {
- return new ParcelableWrapper(readCutout(in));
+ return new ParcelableWrapper(readCutoutFromParcel(in));
}
@Override
@@ -360,8 +379,17 @@
}
};
- private static DisplayCutout readCutout(Parcel in) {
- if (in.readInt() == 0) {
+ /**
+ * Reads a DisplayCutout from a {@link Parcel}.
+ *
+ * @see #writeCutoutToParcel(DisplayCutout, Parcel, int)
+ */
+ public static DisplayCutout readCutoutFromParcel(Parcel in) {
+ int variant = in.readInt();
+ if (variant == -1) {
+ return null;
+ }
+ if (variant == 0) {
return NO_CUTOUT;
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index b813ddb..37e9815 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -149,6 +149,13 @@
public int overscanBottom;
/**
+ * The {@link DisplayCutout} if present, otherwise {@code null}.
+ *
+ * @hide
+ */
+ public DisplayCutout displayCutout;
+
+ /**
* The rotation of the display relative to its natural orientation.
* May be one of {@link android.view.Surface#ROTATION_0},
* {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
@@ -301,6 +308,7 @@
&& overscanTop == other.overscanTop
&& overscanRight == other.overscanRight
&& overscanBottom == other.overscanBottom
+ && Objects.equal(displayCutout, other.displayCutout)
&& rotation == other.rotation
&& modeId == other.modeId
&& defaultModeId == other.defaultModeId
@@ -342,6 +350,7 @@
overscanTop = other.overscanTop;
overscanRight = other.overscanRight;
overscanBottom = other.overscanBottom;
+ displayCutout = other.displayCutout;
rotation = other.rotation;
modeId = other.modeId;
defaultModeId = other.defaultModeId;
@@ -379,6 +388,7 @@
overscanTop = source.readInt();
overscanRight = source.readInt();
overscanBottom = source.readInt();
+ displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source);
rotation = source.readInt();
modeId = source.readInt();
defaultModeId = source.readInt();
@@ -425,6 +435,7 @@
dest.writeInt(overscanTop);
dest.writeInt(overscanRight);
dest.writeInt(overscanBottom);
+ DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags);
dest.writeInt(rotation);
dest.writeInt(modeId);
dest.writeInt(defaultModeId);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 9e103a3..7001067 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -396,4 +396,19 @@
* Return the touch region for the current IME window, or an empty region if there is none.
*/
Region getCurrentImeTouchRegion();
+
+ /**
+ * Starts a window trace.
+ */
+ void startWindowTrace();
+
+ /**
+ * Stops a window trace.
+ */
+ void stopWindowTrace();
+
+ /**
+ * Returns true if window trace is enabled.
+ */
+ boolean isWindowTraceEnabled();
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index ab0b3ee..fbba8ab 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -47,6 +47,7 @@
private final int mGravity;
private View mAppName;
private View mHeaderText;
+ private View mSecondaryHeaderText;
private OnClickListener mExpandClickListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private ImageView mExpandButton;
@@ -58,7 +59,6 @@
private boolean mShowExpandButtonAtEnd;
private boolean mShowWorkBadgeAtEnd;
private Drawable mBackground;
- private int mHeaderBackgroundHeight;
private boolean mEntireHeaderClickable;
private boolean mExpandOnlyOnButton;
private boolean mAcceptAllTouches;
@@ -68,7 +68,7 @@
@Override
public void getOutline(View view, Outline outline) {
if (mBackground != null) {
- outline.setRect(0, 0, getWidth(), mHeaderBackgroundHeight);
+ outline.setRect(0, 0, getWidth(), getHeight());
outline.setAlpha(1f);
}
}
@@ -91,8 +91,6 @@
Resources res = getResources();
mChildMinWidth = res.getDimensionPixelSize(R.dimen.notification_header_shrink_min_width);
mContentEndMargin = res.getDimensionPixelSize(R.dimen.notification_content_margin_end);
- mHeaderBackgroundHeight = res.getDimensionPixelSize(
- R.dimen.notification_header_background_height);
mEntireHeaderClickable = res.getBoolean(R.bool.config_notificationHeaderClickableForExpand);
int[] attrIds = { android.R.attr.gravity };
@@ -106,6 +104,7 @@
super.onFinishInflate();
mAppName = findViewById(com.android.internal.R.id.app_name_text);
mHeaderText = findViewById(com.android.internal.R.id.header_text);
+ mSecondaryHeaderText = findViewById(com.android.internal.R.id.header_text_secondary);
mExpandButton = findViewById(com.android.internal.R.id.expand_button);
mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
@@ -137,26 +136,33 @@
if (totalWidth > givenWidth) {
int overFlow = totalWidth - givenWidth;
// We are overflowing, lets shrink the app name first
- final int appWidth = mAppName.getMeasuredWidth();
- if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) {
- int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mAppName.measure(childWidthSpec, wrapContentHeightSpec);
- overFlow -= appWidth - newSize;
- }
- // still overflowing, finaly we shrink the header text
- if (overFlow > 0 && mHeaderText.getVisibility() != GONE) {
- // we're still too big
- final int textWidth = mHeaderText.getMeasuredWidth();
- int newSize = Math.max(0, textWidth - overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mHeaderText.measure(childWidthSpec, wrapContentHeightSpec);
- }
+ overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
+ mChildMinWidth);
+
+ // still overflowing, we shrink the header text
+ overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mHeaderText, 0);
+
+ // still overflowing, finally we shrink the secondary header text
+ shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
+ 0);
}
mTotalWidth = Math.min(totalWidth, givenWidth);
setMeasuredDimension(givenWidth, givenHeight);
}
+ private int shrinkViewForOverflow(int heightSpec, int overFlow, View targetView,
+ int minimumWidth) {
+ final int oldWidth = targetView.getMeasuredWidth();
+ if (overFlow > 0 && targetView.getVisibility() != GONE && oldWidth > minimumWidth) {
+ // we're still too big
+ int newSize = Math.max(minimumWidth, oldWidth - overFlow);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
+ targetView.measure(childWidthSpec, heightSpec);
+ overFlow -= oldWidth - newSize;
+ }
+ return overFlow;
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingStart();
@@ -228,7 +234,7 @@
@Override
protected void onDraw(Canvas canvas) {
if (mBackground != null) {
- mBackground.setBounds(0, 0, getWidth(), mHeaderBackgroundHeight);
+ mBackground.setBounds(0, 0, getWidth(), getHeight());
mBackground.draw(canvas);
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a417a4a..1f7f8b9 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -182,6 +182,11 @@
* SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
* SurfaceTexture#updateTexImage}.
*
+ * Please note that holding onto the Surface created here is not enough to
+ * keep the provided SurfaceTexture from being reclaimed. In that sense,
+ * the Surface will act like a
+ * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
+ *
* @param surfaceTexture The {@link SurfaceTexture} that is updated by this
* Surface.
* @throws OutOfResourcesException if the surface could not be created.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 268e460..bd7f8e5 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -16,20 +16,22 @@
package android.view;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+import static android.view.SurfaceControlProto.HASH_CODE;
+import static android.view.SurfaceControlProto.NAME;
import android.annotation.Size;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
-import android.graphics.PixelFormat;
import android.graphics.Matrix;
+import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
@@ -40,11 +42,13 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import android.view.Surface.OutOfResourcesException;
import com.android.internal.annotations.GuardedBy;
import dalvik.system.CloseGuard;
+
import libcore.util.NativeAllocationRegistry;
import java.io.Closeable;
@@ -628,6 +632,21 @@
nativeWriteToParcel(mNativeObject, dest);
}
+ /**
+ * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
+ * android.view.SurfaceControlProto}.
+ *
+ * @param proto Stream to write the SurfaceControl object to.
+ * @param fieldId Field Id of the SurfaceControl as defined in the parent message.
+ * @hide
+ */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(HASH_CODE, System.identityHashCode(this));
+ proto.write(NAME, mName);
+ proto.end(token);
+ }
+
public static final Creator<SurfaceControl> CREATOR
= new Creator<SurfaceControl>() {
public SurfaceControl createFromParcel(Parcel in) {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 6a8f8b1..8b730f2 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -969,8 +969,6 @@
mInitialized = true;
mAppContext = context.getApplicationContext();
- // b/68769804: For low FPS experiments.
- setFPSDivisor(SystemProperties.getInt(DEBUG_FPS_DIVISOR, 1));
initSched(renderProxy);
initGraphicsStats();
}
@@ -1025,9 +1023,7 @@
/** b/68769804: For low FPS experiments. */
public static void setFPSDivisor(int divisor) {
- if (divisor <= 0) divisor = 1;
- Choreographer.getInstance().setFPSDivisor(divisor);
- nHackySetRTAnimationsEnabled(divisor == 1);
+ nHackySetRTAnimationsEnabled(divisor <= 1);
}
/** Not actually public - internal use only. This doc to make lint happy */
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 21943bd..9c1c9e3 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -18,8 +18,6 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import android.annotation.SystemApi;
-
/**
* Constants for interfacing with WindowManagerService and WindowManagerPolicyInternal.
* @hide
@@ -62,7 +60,6 @@
* Set to {@code true} when intent was invoked from pressing the home key.
* @hide
*/
- @SystemApi
String EXTRA_FROM_HOME_KEY = "android.intent.extra.FROM_HOME_KEY";
// TODO: move this to a more appropriate place.
diff --git a/core/java/android/webkit/FindAddress.java b/core/java/android/webkit/FindAddress.java
new file mode 100644
index 0000000..31b2427
--- /dev/null
+++ b/core/java/android/webkit/FindAddress.java
@@ -0,0 +1,478 @@
+/*
+ * 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.webkit;
+
+import java.util.Locale;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Java implementation of legacy WebView.findAddress algorithm.
+ *
+ * @hide
+ */
+class FindAddress {
+ static class ZipRange {
+ int mLow;
+ int mHigh;
+ int mException1;
+ int mException2;
+ ZipRange(int low, int high, int exception1, int exception2) {
+ mLow = low;
+ mHigh = high;
+ mException1 = exception1;
+ mException2 = exception1;
+ }
+ boolean matches(String zipCode) {
+ int prefix = Integer.parseInt(zipCode.substring(0, 2));
+ return (mLow <= prefix && prefix <= mHigh) || prefix == mException1
+ || prefix == mException2;
+ }
+ }
+
+ // Addresses consist of at least this many words, not including state and zip code.
+ private static final int MIN_ADDRESS_WORDS = 4;
+
+ // Adddresses consist of at most this many words, not including state and zip code.
+ private static final int MAX_ADDRESS_WORDS = 14;
+
+ // Addresses consist of at most this many lines.
+ private static final int MAX_ADDRESS_LINES = 5;
+
+ // No words in an address are longer than this many characters.
+ private static final int kMaxAddressNameWordLength = 25;
+
+ // Location name should be in the first MAX_LOCATION_NAME_DISTANCE words
+ private static final int MAX_LOCATION_NAME_DISTANCE = 5;
+
+ private static final ZipRange[] sStateZipCodeRanges = {
+ new ZipRange(99, 99, -1, -1), // AK Alaska.
+ new ZipRange(35, 36, -1, -1), // AL Alabama.
+ new ZipRange(71, 72, -1, -1), // AR Arkansas.
+ new ZipRange(96, 96, -1, -1), // AS American Samoa.
+ new ZipRange(85, 86, -1, -1), // AZ Arizona.
+ new ZipRange(90, 96, -1, -1), // CA California.
+ new ZipRange(80, 81, -1, -1), // CO Colorado.
+ new ZipRange(6, 6, -1, -1), // CT Connecticut.
+ new ZipRange(20, 20, -1, -1), // DC District of Columbia.
+ new ZipRange(19, 19, -1, -1), // DE Delaware.
+ new ZipRange(32, 34, -1, -1), // FL Florida.
+ new ZipRange(96, 96, -1, -1), // FM Federated States of Micronesia.
+ new ZipRange(30, 31, -1, -1), // GA Georgia.
+ new ZipRange(96, 96, -1, -1), // GU Guam.
+ new ZipRange(96, 96, -1, -1), // HI Hawaii.
+ new ZipRange(50, 52, -1, -1), // IA Iowa.
+ new ZipRange(83, 83, -1, -1), // ID Idaho.
+ new ZipRange(60, 62, -1, -1), // IL Illinois.
+ new ZipRange(46, 47, -1, -1), // IN Indiana.
+ new ZipRange(66, 67, 73, -1), // KS Kansas.
+ new ZipRange(40, 42, -1, -1), // KY Kentucky.
+ new ZipRange(70, 71, -1, -1), // LA Louisiana.
+ new ZipRange(1, 2, -1, -1), // MA Massachusetts.
+ new ZipRange(20, 21, -1, -1), // MD Maryland.
+ new ZipRange(3, 4, -1, -1), // ME Maine.
+ new ZipRange(96, 96, -1, -1), // MH Marshall Islands.
+ new ZipRange(48, 49, -1, -1), // MI Michigan.
+ new ZipRange(55, 56, -1, -1), // MN Minnesota.
+ new ZipRange(63, 65, -1, -1), // MO Missouri.
+ new ZipRange(96, 96, -1, -1), // MP Northern Mariana Islands.
+ new ZipRange(38, 39, -1, -1), // MS Mississippi.
+ new ZipRange(55, 56, -1, -1), // MT Montana.
+ new ZipRange(27, 28, -1, -1), // NC North Carolina.
+ new ZipRange(58, 58, -1, -1), // ND North Dakota.
+ new ZipRange(68, 69, -1, -1), // NE Nebraska.
+ new ZipRange(3, 4, -1, -1), // NH New Hampshire.
+ new ZipRange(7, 8, -1, -1), // NJ New Jersey.
+ new ZipRange(87, 88, 86, -1), // NM New Mexico.
+ new ZipRange(88, 89, 96, -1), // NV Nevada.
+ new ZipRange(10, 14, 0, 6), // NY New York.
+ new ZipRange(43, 45, -1, -1), // OH Ohio.
+ new ZipRange(73, 74, -1, -1), // OK Oklahoma.
+ new ZipRange(97, 97, -1, -1), // OR Oregon.
+ new ZipRange(15, 19, -1, -1), // PA Pennsylvania.
+ new ZipRange(6, 6, 0, 9), // PR Puerto Rico.
+ new ZipRange(96, 96, -1, -1), // PW Palau.
+ new ZipRange(2, 2, -1, -1), // RI Rhode Island.
+ new ZipRange(29, 29, -1, -1), // SC South Carolina.
+ new ZipRange(57, 57, -1, -1), // SD South Dakota.
+ new ZipRange(37, 38, -1, -1), // TN Tennessee.
+ new ZipRange(75, 79, 87, 88), // TX Texas.
+ new ZipRange(84, 84, -1, -1), // UT Utah.
+ new ZipRange(22, 24, 20, -1), // VA Virginia.
+ new ZipRange(6, 9, -1, -1), // VI Virgin Islands.
+ new ZipRange(5, 5, -1, -1), // VT Vermont.
+ new ZipRange(98, 99, -1, -1), // WA Washington.
+ new ZipRange(53, 54, -1, -1), // WI Wisconsin.
+ new ZipRange(24, 26, -1, -1), // WV West Virginia.
+ new ZipRange(82, 83, -1, -1) // WY Wyoming.
+ };
+
+ // Newlines
+ private static final String NL = "\n\u000B\u000C\r\u0085\u2028\u2029";
+
+ // Space characters
+ private static final String SP = "\u0009\u0020\u00A0\u1680\u2000\u2001"
+ + "\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F"
+ + "\u205F\u3000";
+
+ // Whitespace
+ private static final String WS = SP + NL;
+
+ // Characters that are considered word delimiters.
+ private static final String WORD_DELIM = ",*\u2022" + WS;
+
+ // Lookahead for word end.
+ private static final String WORD_END = "(?=[" + WORD_DELIM + "]|$)";
+
+ // Address words are a sequence of non-delimiter characters.
+ private static final Pattern sWordRe =
+ Pattern.compile("[^" + WORD_DELIM + "]+" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+ // Characters that are considered suffix delimiters for house numbers.
+ private static final String HOUSE_POST_DELIM = ",\"'" + WS;
+
+ // Lookahead for house end.
+ private static final String HOUSE_END = "(?=[" + HOUSE_POST_DELIM + "]|$)";
+
+ // Characters that are considered prefix delimiters for house numbers.
+ private static final String HOUSE_PRE_DELIM = ":" + HOUSE_POST_DELIM;
+
+ // A house number component is "one" or a number, optionally
+ // followed by a single alphabetic character, or
+ private static final String HOUSE_COMPONENT = "(?:one|\\d+([a-z](?=[^a-z]|$)|st|nd|rd|th)?)";
+
+ // House numbers are a repetition of |HOUSE_COMPONENT|, separated by -, and followed by
+ // a delimiter character.
+ private static final Pattern sHouseNumberRe =
+ Pattern.compile(HOUSE_COMPONENT + "(?:-" + HOUSE_COMPONENT + ")*" + HOUSE_END,
+ Pattern.CASE_INSENSITIVE);
+
+ // XXX: do we want to accept whitespace other than 0x20 in state names?
+ private static final Pattern sStateRe = Pattern.compile("(?:"
+ + "(ak|alaska)|"
+ + "(al|alabama)|"
+ + "(ar|arkansas)|"
+ + "(as|american[" + SP + "]+samoa)|"
+ + "(az|arizona)|"
+ + "(ca|california)|"
+ + "(co|colorado)|"
+ + "(ct|connecticut)|"
+ + "(dc|district[" + SP + "]+of[" + SP + "]+columbia)|"
+ + "(de|delaware)|"
+ + "(fl|florida)|"
+ + "(fm|federated[" + SP + "]+states[" + SP + "]+of[" + SP + "]+micronesia)|"
+ + "(ga|georgia)|"
+ + "(gu|guam)|"
+ + "(hi|hawaii)|"
+ + "(ia|iowa)|"
+ + "(id|idaho)|"
+ + "(il|illinois)|"
+ + "(in|indiana)|"
+ + "(ks|kansas)|"
+ + "(ky|kentucky)|"
+ + "(la|louisiana)|"
+ + "(ma|massachusetts)|"
+ + "(md|maryland)|"
+ + "(me|maine)|"
+ + "(mh|marshall[" + SP + "]+islands)|"
+ + "(mi|michigan)|"
+ + "(mn|minnesota)|"
+ + "(mo|missouri)|"
+ + "(mp|northern[" + SP + "]+mariana[" + SP + "]+islands)|"
+ + "(ms|mississippi)|"
+ + "(mt|montana)|"
+ + "(nc|north[" + SP + "]+carolina)|"
+ + "(nd|north[" + SP + "]+dakota)|"
+ + "(ne|nebraska)|"
+ + "(nh|new[" + SP + "]+hampshire)|"
+ + "(nj|new[" + SP + "]+jersey)|"
+ + "(nm|new[" + SP + "]+mexico)|"
+ + "(nv|nevada)|"
+ + "(ny|new[" + SP + "]+york)|"
+ + "(oh|ohio)|"
+ + "(ok|oklahoma)|"
+ + "(or|oregon)|"
+ + "(pa|pennsylvania)|"
+ + "(pr|puerto[" + SP + "]+rico)|"
+ + "(pw|palau)|"
+ + "(ri|rhode[" + SP + "]+island)|"
+ + "(sc|south[" + SP + "]+carolina)|"
+ + "(sd|south[" + SP + "]+dakota)|"
+ + "(tn|tennessee)|"
+ + "(tx|texas)|"
+ + "(ut|utah)|"
+ + "(va|virginia)|"
+ + "(vi|virgin[" + SP + "]+islands)|"
+ + "(vt|vermont)|"
+ + "(wa|washington)|"
+ + "(wi|wisconsin)|"
+ + "(wv|west[" + SP + "]+virginia)|"
+ + "(wy|wyoming)"
+ + ")" + WORD_END,
+ Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sLocationNameRe = Pattern.compile("(?:"
+ + "alley|annex|arcade|ave[.]?|avenue|alameda|bayou|"
+ + "beach|bend|bluffs?|bottom|boulevard|branch|bridge|"
+ + "brooks?|burgs?|bypass|broadway|camino|camp|canyon|"
+ + "cape|causeway|centers?|circles?|cliffs?|club|common|"
+ + "corners?|course|courts?|coves?|creek|crescent|crest|"
+ + "crossing|crossroad|curve|circulo|dale|dam|divide|"
+ + "drives?|estates?|expressway|extensions?|falls?|ferry|"
+ + "fields?|flats?|fords?|forest|forges?|forks?|fort|"
+ + "freeway|gardens?|gateway|glens?|greens?|groves?|"
+ + "harbors?|haven|heights|highway|hills?|hollow|inlet|"
+ + "islands?|isle|junctions?|keys?|knolls?|lakes?|land|"
+ + "landing|lane|lights?|loaf|locks?|lodge|loop|mall|"
+ + "manors?|meadows?|mews|mills?|mission|motorway|mount|"
+ + "mountains?|neck|orchard|oval|overpass|parks?|"
+ + "parkways?|pass|passage|path|pike|pines?|plains?|"
+ + "plaza|points?|ports?|prairie|privada|radial|ramp|"
+ + "ranch|rapids?|rd[.]?|rest|ridges?|river|roads?|route|"
+ + "row|rue|run|shoals?|shores?|skyway|springs?|spurs?|"
+ + "squares?|station|stravenue|stream|st[.]?|streets?|"
+ + "summit|speedway|terrace|throughway|trace|track|"
+ + "trafficway|trail|tunnel|turnpike|underpass|unions?|"
+ + "valleys?|viaduct|views?|villages?|ville|vista|walks?|"
+ + "wall|ways?|wells?|xing|xrd)" + WORD_END,
+ Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sSuffixedNumberRe =
+ Pattern.compile("(\\d+)(st|nd|rd|th)", Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern sZipCodeRe =
+ Pattern.compile("(?:\\d{5}(?:-\\d{4})?)" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+ private static boolean checkHouseNumber(String houseNumber) {
+ // Make sure that there are at most 5 digits.
+ int digitCount = 0;
+ for (int i = 0; i < houseNumber.length(); ++i) {
+ if (Character.isDigit(houseNumber.charAt(i))) ++digitCount;
+ }
+ if (digitCount > 5) return false;
+
+ // Make sure that any ordinals are valid.
+ Matcher suffixMatcher = sSuffixedNumberRe.matcher(houseNumber);
+ while (suffixMatcher.find()) {
+ int num = Integer.parseInt(suffixMatcher.group(1));
+ if (num == 0) {
+ return false; // 0th is invalid.
+ }
+ String suffix = suffixMatcher.group(2).toLowerCase(Locale.getDefault());
+ switch (num % 10) {
+ case 1:
+ return suffix.equals(num % 100 == 11 ? "th" : "st");
+ case 2:
+ return suffix.equals(num % 100 == 12 ? "th" : "nd");
+ case 3:
+ return suffix.equals(num % 100 == 13 ? "th" : "rd");
+ default:
+ return suffix.equals("th");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Attempt to match a house number beginnning at position offset
+ * in content. The house number must be followed by a word
+ * delimiter or the end of the string, and if offset is non-zero,
+ * then it must also be preceded by a word delimiter.
+ *
+ * @return a MatchResult if a valid house number was found.
+ */
+ private static MatchResult matchHouseNumber(String content, int offset) {
+ if (offset > 0 && HOUSE_PRE_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+ Matcher matcher = sHouseNumberRe.matcher(content).region(offset, content.length());
+ if (matcher.lookingAt()) {
+ MatchResult matchResult = matcher.toMatchResult();
+ if (checkHouseNumber(matchResult.group(0))) return matchResult;
+ }
+ return null;
+ }
+
+ /**
+ * Attempt to match a US state beginnning at position offset in
+ * content. The matching state must be followed by a word
+ * delimiter or the end of the string, and if offset is non-zero,
+ * then it must also be preceded by a word delimiter.
+ *
+ * @return a MatchResult if a valid US state (or two letter code)
+ * was found.
+ */
+ private static MatchResult matchState(String content, int offset) {
+ if (offset > 0 && WORD_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+ Matcher stateMatcher = sStateRe.matcher(content).region(offset, content.length());
+ return stateMatcher.lookingAt() ? stateMatcher.toMatchResult() : null;
+ }
+
+ /**
+ * Test whether zipCode matches the U.S. zip code format (ddddd or
+ * ddddd-dddd) and is within the expected range, given that
+ * stateMatch is a match of sStateRe.
+ *
+ * @return true if zipCode is a valid zip code, is legal for the
+ * matched state, and is followed by a word delimiter or the end
+ * of the string.
+ */
+ private static boolean isValidZipCode(String zipCode, MatchResult stateMatch) {
+ if (stateMatch == null) return false;
+ // Work out the index of the state, based on which group matched.
+ int stateIndex = stateMatch.groupCount();
+ while (stateIndex > 0) {
+ if (stateMatch.group(stateIndex--) != null) break;
+ }
+ return sZipCodeRe.matcher(zipCode).matches()
+ && sStateZipCodeRanges[stateIndex].matches(zipCode);
+ }
+
+ /**
+ * Test whether location is one of the valid locations.
+ *
+ * @return true if location starts with a valid location name
+ * followed by a word delimiter or the end of the string.
+ */
+ private static boolean isValidLocationName(String location) {
+ return sLocationNameRe.matcher(location).matches();
+ }
+
+ /**
+ * Attempt to match a complete address in content, starting with
+ * houseNumberMatch.
+ *
+ * @param content The string to search.
+ * @param houseNumberMatch A matching house number to start extending.
+ * @return +ve: the end of the match
+ * +ve: the position to restart searching for house numbers, negated.
+ */
+ private static int attemptMatch(String content, MatchResult houseNumberMatch) {
+ int restartPos = -1;
+ int nonZipMatch = -1;
+ int it = houseNumberMatch.end();
+ int numLines = 1;
+ boolean consecutiveHouseNumbers = true;
+ boolean foundLocationName = false;
+ int wordCount = 1;
+ String lastWord = "";
+
+ Matcher matcher = sWordRe.matcher(content);
+
+ for (; it < content.length(); lastWord = matcher.group(0), it = matcher.end()) {
+ if (!matcher.find(it)) {
+ // No more words in the input sequence.
+ return -content.length();
+ }
+ if (matcher.end() - matcher.start() > kMaxAddressNameWordLength) {
+ // Word is too long to be part of an address. Fail.
+ return -matcher.end();
+ }
+
+ // Count the number of newlines we just consumed.
+ while (it < matcher.start()) {
+ if (NL.indexOf(content.charAt(it++)) != -1) ++numLines;
+ }
+
+ // Consumed too many lines. Fail.
+ if (numLines > MAX_ADDRESS_LINES) break;
+
+ // Consumed too many words. Fail.
+ if (++wordCount > MAX_ADDRESS_WORDS) break;
+
+ if (matchHouseNumber(content, it) != null) {
+ if (consecutiveHouseNumbers && numLines > 1) {
+ // Last line ended with a number, and this this line starts with one.
+ // Restart at this number.
+ return -it;
+ }
+ // Remember the position of this match as the restart position.
+ if (restartPos == -1) restartPos = it;
+ continue;
+ }
+
+ consecutiveHouseNumbers = false;
+
+ if (isValidLocationName(matcher.group(0))) {
+ foundLocationName = true;
+ continue;
+ }
+
+ if (wordCount == MAX_LOCATION_NAME_DISTANCE && !foundLocationName) {
+ // Didn't find a location name in time. Fail.
+ it = matcher.end();
+ break;
+ }
+
+ if (foundLocationName && wordCount > MIN_ADDRESS_WORDS) {
+ // We can now attempt to match a state.
+ MatchResult stateMatch = matchState(content, it);
+ if (stateMatch != null) {
+ if (lastWord.equals("et") && stateMatch.group(0).equals("al")) {
+ // Reject "et al" as a false postitive.
+ it = stateMatch.end();
+ break;
+ }
+
+ // At this point we've matched a state; try to match a zip code after it.
+ Matcher zipMatcher = sWordRe.matcher(content);
+ if (zipMatcher.find(stateMatch.end())
+ && isValidZipCode(zipMatcher.group(0), stateMatch)) {
+ return zipMatcher.end();
+ }
+ // The content ends with a state but no zip
+ // code. This is a legal match according to the
+ // documentation. N.B. This differs from the
+ // original c++ implementation, which only allowed
+ // the zip code to be optional at the end of the
+ // string, which presumably is a bug. Now we
+ // prefer to find a match with a zip code, but
+ // remember non-zip matches and return them if
+ // necessary.
+ nonZipMatch = stateMatch.end();
+ }
+ }
+ }
+
+ if (nonZipMatch > 0) return nonZipMatch;
+
+ return -(restartPos > 0 ? restartPos : it);
+ }
+
+ /**
+ * Return the first matching address in content.
+ *
+ * @param content The string to search.
+ * @return The first valid address, or null if no address was matched.
+ */
+ static String findAddress(String content) {
+ Matcher houseNumberMatcher = sHouseNumberRe.matcher(content);
+ int start = 0;
+ while (houseNumberMatcher.find(start)) {
+ if (checkHouseNumber(houseNumberMatcher.group(0))) {
+ start = houseNumberMatcher.start();
+ int end = attemptMatch(content, houseNumberMatcher);
+ if (end > 0) {
+ return content.substring(start, end);
+ }
+ start = -end;
+ } else {
+ start = houseNumberMatcher.end();
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index de5a822..deb94e81 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -129,8 +129,10 @@
* String summary = "<html><body>You scored <b>192</b> points.</body></html>";
* webview.loadData(summary, "text/html", null);
* // ... although note that there are restrictions on what this HTML can do.
- * // See the JavaDocs for {@link #loadData(String,String,String) loadData()} and {@link
- * #loadDataWithBaseURL(String,String,String,String,String) loadDataWithBaseURL()} for more info.
+ * // See {@link #loadData(String,String,String)} and {@link
+ * #loadDataWithBaseURL(String,String,String,String,String)} for more info.
+ * // Also see {@link #loadData(String,String,String)} for information on encoding special
+ * // characters.
* </pre>
*
* <p>A WebView has several customization points where you can add your
@@ -989,13 +991,21 @@
* #loadDataWithBaseURL(String,String,String,String,String)
* loadDataWithBaseURL()} with an appropriate base URL.
* <p>
- * The encoding parameter specifies whether the data is base64 or URL
+ * The {@code encoding} parameter specifies whether the data is base64 or URL
* encoded. If the data is base64 encoded, the value of the encoding
- * parameter must be 'base64'. For all other values of the parameter,
- * including {@code null}, it is assumed that the data uses ASCII encoding for
- * octets inside the range of safe URL characters and use the standard %xx
- * hex encoding of URLs for octets outside that range. For example, '#',
- * '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
+ * parameter must be 'base64'. HTML can be encoded with {@link
+ * android.util.Base64#encodeToString(byte[],int)} like so:
+ * <pre>
+ * String unencodedHtml =
+ * "<html><body>'%28' is the code for '('</body></html>";
+ * String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING);
+ * webView.loadData(encodedHtml, "text/html", "base64");
+ * </pre>
+ * <p>
+ * For all other values of {@code encoding} (including {@code null}) it is assumed that the
+ * data uses ASCII encoding for octets inside the range of safe URL characters and use the
+ * standard %xx hex encoding of URLs for octets outside that range. See <a
+ * href="https://tools.ietf.org/html/rfc3986#section-2.2">RFC 3986</a> for more information.
* <p>
* The {@code mimeType} parameter specifies the format of the data.
* If WebView can't handle the specified MIME type, it will download the data.
@@ -1821,9 +1831,10 @@
*/
@Nullable
public static String findAddress(String addr) {
- // TODO: Rewrite this in Java so it is not needed to start up chromium
- // Could also be deprecated
- return getFactory().getStatics().findAddress(addr);
+ if (addr == null) {
+ throw new NullPointerException("addr is null");
+ }
+ return FindAddress.findAddress(addr);
}
/**
diff --git a/core/java/android/widget/MediaController2.java b/core/java/android/widget/MediaController2.java
new file mode 100644
index 0000000..9035137
--- /dev/null
+++ b/core/java/android/widget/MediaController2.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.media.session.MediaController;
+import android.media.update.ApiLoader;
+import android.media.update.MediaController2Provider;
+import android.media.update.ViewProvider;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+/**
+ * TODO PUBLIC API
+ * @hide
+ */
+public class MediaController2 extends FrameLayout {
+ private final MediaController2Provider mProvider;
+
+ public MediaController2(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ mProvider = ApiLoader.getProvider(context)
+ .createMediaController2(this, new SuperProvider());
+ }
+
+ public void setController(MediaController controller) {
+ mProvider.setController_impl(controller);
+ }
+
+ public void setAnchorView(View view) {
+ mProvider.setAnchorView_impl(view);
+ }
+
+ public void show() {
+ mProvider.show_impl();
+ }
+
+ public void show(int timeout) {
+ mProvider.show_impl(timeout);
+ }
+
+ public boolean isShowing() {
+ return mProvider.isShowing_impl();
+ }
+
+ public void hide() {
+ mProvider.hide_impl();
+ }
+
+ public void setPrevNextListeners(OnClickListener next, OnClickListener prev) {
+ mProvider.setPrevNextListeners_impl(next, prev);
+ }
+
+ public void showCCButton() {
+ mProvider.showCCButton_impl();
+ }
+
+ public boolean isPlaying() {
+ return mProvider.isPlaying_impl();
+ }
+
+ public int getCurrentPosition() {
+ return mProvider.getCurrentPosition_impl();
+ }
+
+ public int getBufferPercentage() {
+ return mProvider.getBufferPercentage_impl();
+ }
+
+ public boolean canPause() {
+ return mProvider.canPause_impl();
+ }
+
+ public boolean canSeekBackward() {
+ return mProvider.canSeekBackward_impl();
+ }
+
+ public boolean canSeekForward() {
+ return mProvider.canSeekForward_impl();
+ }
+
+ public void showSubtitle() {
+ mProvider.showSubtitle_impl();
+ }
+
+ public void hideSubtitle() {
+ mProvider.hideSubtitle_impl();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ mProvider.onAttachedToWindow_impl();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mProvider.onDetachedFromWindow_impl();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ mProvider.onLayout_impl(changed, left, top, right, bottom);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mProvider.draw_impl(canvas);
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return mProvider.getAccessibilityClassName_impl();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return mProvider.onTouchEvent_impl(ev);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent ev) {
+ return mProvider.onTrackballEvent_impl(ev);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return mProvider.onKeyDown_impl(keyCode, event);
+ }
+
+ @Override
+ public void onFinishInflate() {
+ mProvider.onFinishInflate_impl();
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return mProvider.dispatchKeyEvent_impl(event);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mProvider.setEnabled_impl(enabled);
+ }
+
+ private class SuperProvider implements ViewProvider {
+ @Override
+ public void onAttachedToWindow_impl() {
+ MediaController2.super.onAttachedToWindow();
+ }
+
+ @Override
+ public void onDetachedFromWindow_impl() {
+ MediaController2.super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
+ MediaController2.super.onLayout(changed, left, top, right, bottom);
+ }
+
+ @Override
+ public void draw_impl(Canvas canvas) {
+ MediaController2.super.draw(canvas);
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName_impl() {
+ return MediaController2.super.getAccessibilityClassName();
+ }
+
+ @Override
+ public boolean onTouchEvent_impl(MotionEvent ev) {
+ return MediaController2.super.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTrackballEvent_impl(MotionEvent ev) {
+ return MediaController2.super.onTrackballEvent(ev);
+ }
+
+ @Override
+ public boolean onKeyDown_impl(int keyCode, KeyEvent event) {
+ return MediaController2.super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public void onFinishInflate_impl() {
+ MediaController2.super.onFinishInflate();
+ }
+
+ @Override
+ public boolean dispatchKeyEvent_impl(KeyEvent event) {
+ return MediaController2.super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public void setEnabled_impl(boolean enabled) {
+ MediaController2.super.setEnabled(enabled);
+ }
+ }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1618d62..cae2d7d9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -296,6 +296,7 @@
* @attr ref android.R.styleable#TextView_imeActionId
* @attr ref android.R.styleable#TextView_editorExtras
* @attr ref android.R.styleable#TextView_elegantTextHeight
+ * @attr ref android.R.styleable#TextView_fallbackLineSpacing
* @attr ref android.R.styleable#TextView_letterSpacing
* @attr ref android.R.styleable#TextView_fontFeatureSettings
* @attr ref android.R.styleable#TextView_breakStrategy
@@ -310,7 +311,6 @@
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
static final String LOG_TAG = "TextView";
static final boolean DEBUG_EXTRACT = false;
- static final boolean DEBUG_AUTOFILL = false;
private static final float[] TEMP_POSITION = new float[2];
// Enum for the "typeface" XML parameter.
@@ -655,7 +655,7 @@
// True if internationalized input should be used for numbers and date and time.
private final boolean mUseInternationalizedInput;
// True if fallback fonts that end up getting used should be allowed to affect line spacing.
- /* package */ final boolean mUseFallbackLineSpacing;
+ /* package */ boolean mUseFallbackLineSpacing;
@ViewDebug.ExportedProperty(category = "text")
private int mGravity = Gravity.TOP | Gravity.START;
@@ -788,7 +788,7 @@
// Indicates whether the text was set statically or dynamically, so it can be used to
// sanitize autofill requests.
- private boolean mSetFromXmlOrResourceId = false;
+ private boolean mTextSetFromXmlOrResourceId = false;
// Resource id used to set the text - used for autofill purposes.
private @StringRes int mTextId = ResourceId.ID_NULL;
@@ -930,7 +930,7 @@
int n = a.getIndexCount();
// Must set id in a temporary variable because it will be reset by setText()
- boolean setFromXml = false;
+ boolean textIsSetFromXml = false;
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
@@ -1072,7 +1072,7 @@
break;
case com.android.internal.R.styleable.TextView_text:
- setFromXml = true;
+ textIsSetFromXml = true;
mTextId = a.getResourceId(attr, ResourceId.ID_NULL);
text = a.getText(attr);
break;
@@ -1465,8 +1465,8 @@
}
setText(text, bufferType);
- if (setFromXml) {
- mSetFromXmlOrResourceId = true;
+ if (textIsSetFromXml) {
+ mTextSetFromXmlOrResourceId = true;
}
if (hint != null) setHint(hint);
@@ -3255,6 +3255,8 @@
float mShadowDx = 0, mShadowDy = 0, mShadowRadius = 0;
boolean mHasElegant = false;
boolean mElegant = false;
+ boolean mHasFallbackLineSpacing = false;
+ boolean mFallbackLineSpacing = false;
boolean mHasLetterSpacing = false;
float mLetterSpacing = 0;
String mFontFeatureSettings = null;
@@ -3279,6 +3281,8 @@
+ " mShadowRadius:" + mShadowRadius + "\n"
+ " mHasElegant:" + mHasElegant + "\n"
+ " mElegant:" + mElegant + "\n"
+ + " mHasFallbackLineSpacing:" + mHasFallbackLineSpacing + "\n"
+ + " mFallbackLineSpacing:" + mFallbackLineSpacing + "\n"
+ " mHasLetterSpacing:" + mHasLetterSpacing + "\n"
+ " mLetterSpacing:" + mLetterSpacing + "\n"
+ " mFontFeatureSettings:" + mFontFeatureSettings + "\n"
@@ -3317,6 +3321,8 @@
com.android.internal.R.styleable.TextAppearance_shadowRadius);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_elegantTextHeight,
com.android.internal.R.styleable.TextAppearance_elegantTextHeight);
+ sAppearanceValues.put(com.android.internal.R.styleable.TextView_fallbackLineSpacing,
+ com.android.internal.R.styleable.TextAppearance_fallbackLineSpacing);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_letterSpacing,
com.android.internal.R.styleable.TextAppearance_letterSpacing);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_fontFeatureSettings,
@@ -3407,6 +3413,11 @@
attributes.mHasElegant = true;
attributes.mElegant = appearance.getBoolean(attr, attributes.mElegant);
break;
+ case com.android.internal.R.styleable.TextAppearance_fallbackLineSpacing:
+ attributes.mHasFallbackLineSpacing = true;
+ attributes.mFallbackLineSpacing = appearance.getBoolean(attr,
+ attributes.mFallbackLineSpacing);
+ break;
case com.android.internal.R.styleable.TextAppearance_letterSpacing:
attributes.mHasLetterSpacing = true;
attributes.mLetterSpacing =
@@ -3460,6 +3471,10 @@
setElegantTextHeight(attributes.mElegant);
}
+ if (attributes.mHasFallbackLineSpacing) {
+ setFallbackLineSpacing(attributes.mFallbackLineSpacing);
+ }
+
if (attributes.mHasLetterSpacing) {
setLetterSpacing(attributes.mLetterSpacing);
}
@@ -3741,7 +3756,7 @@
*
* @param elegant set the paint's elegant metrics flag.
*
- * @see Paint#isElegantTextHeight(boolean)
+ * @see Paint#isElegantTextHeight()
*
* @attr ref android.R.styleable#TextView_elegantTextHeight
*/
@@ -3757,6 +3772,43 @@
}
/**
+ * Set whether to respect the ascent and descent of the fallback fonts that are used in
+ * displaying the text (which is needed to avoid text from consecutive lines running into
+ * each other). If set, fallback fonts that end up getting used can increase the ascent
+ * and descent of the lines that they are used on.
+ * <p/>
+ * It is required to be true if text could be in languages like Burmese or Tibetan where text
+ * is typically much taller or deeper than Latin text.
+ *
+ * @param enabled whether to expand linespacing based on fallback fonts, {@code true} by default
+ *
+ * @see StaticLayout.Builder#setUseLineSpacingFromFallbacks(boolean)
+ *
+ * @attr ref android.R.styleable#TextView_fallbackLineSpacing
+ */
+ public void setFallbackLineSpacing(boolean enabled) {
+ if (mUseFallbackLineSpacing != enabled) {
+ mUseFallbackLineSpacing = enabled;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
+ }
+ }
+
+ /**
+ * @return whether fallback line spacing is enabled, {@code true} by default
+ *
+ * @see #setFallbackLineSpacing(boolean)
+ *
+ * @attr ref android.R.styleable#TextView_fallbackLineSpacing
+ */
+ public boolean isFallbackLineSpacing() {
+ return mUseFallbackLineSpacing;
+ }
+
+ /**
* Get the value of the TextView's elegant height metrics flag. This setting selects font
* variants that have not been compacted to fit Latin-based vertical
* metrics, and also increases top and bottom bounds to provide more space.
@@ -5283,7 +5335,7 @@
private void setText(CharSequence text, BufferType type,
boolean notifyBefore, int oldlen) {
- mSetFromXmlOrResourceId = false;
+ mTextSetFromXmlOrResourceId = false;
if (text == null) {
text = "";
}
@@ -5521,7 +5573,7 @@
@android.view.RemotableViewMethod
public final void setText(@StringRes int resid) {
setText(getContext().getResources().getText(resid));
- mSetFromXmlOrResourceId = true;
+ mTextSetFromXmlOrResourceId = true;
mTextId = resid;
}
@@ -5549,7 +5601,7 @@
*/
public final void setText(@StringRes int resid, BufferType type) {
setText(getContext().getResources().getText(resid), type);
- mSetFromXmlOrResourceId = true;
+ mTextSetFromXmlOrResourceId = true;
mTextId = resid;
}
@@ -9463,7 +9515,7 @@
}
final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
- if (DEBUG_AUTOFILL) {
+ if (android.view.autofill.Helper.sVerbose) {
Log.v(LOG_TAG, "sendAfterTextChanged(): notify AFM for text=" + mText);
}
afm.notifyValueChanged(TextView.this);
@@ -10241,9 +10293,16 @@
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
if (forAutofill) {
- structure.setDataIsSensitive(!mSetFromXmlOrResourceId);
+ structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
if (mTextId != ResourceId.ID_NULL) {
- structure.setTextIdEntry(getResources().getResourceEntryName(mTextId));
+ try {
+ structure.setTextIdEntry(getResources().getResourceEntryName(mTextId));
+ } catch (Resources.NotFoundException e) {
+ if (android.view.autofill.Helper.sVerbose) {
+ Log.v(LOG_TAG, "onProvideAutofillStructure(): cannot set name for text id "
+ + mTextId + ": " + e.getMessage());
+ }
+ }
}
}
@@ -11893,7 +11952,7 @@
private final Choreographer mChoreographer;
private byte mStatus = MARQUEE_STOPPED;
- private final float mPixelsPerSecond;
+ private final float mPixelsPerMs;
private float mMaxScroll;
private float mMaxFadeScroll;
private float mGhostStart;
@@ -11906,7 +11965,7 @@
Marquee(TextView v) {
final float density = v.getContext().getResources().getDisplayMetrics().density;
- mPixelsPerSecond = MARQUEE_DP_PER_SECOND * density;
+ mPixelsPerMs = MARQUEE_DP_PER_SECOND * density / 1000f;
mView = new WeakReference<TextView>(v);
mChoreographer = Choreographer.getInstance();
}
@@ -11951,7 +12010,7 @@
long currentMs = mChoreographer.getFrameTime();
long deltaMs = currentMs - mLastAnimationMs;
mLastAnimationMs = currentMs;
- float deltaPx = deltaMs / 1000f * mPixelsPerSecond;
+ float deltaPx = deltaMs * mPixelsPerMs;
mScroll += deltaPx;
if (mScroll > mMaxScroll) {
mScroll = mMaxScroll;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index ab118ba..5d4bccc 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -81,7 +81,11 @@
void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName,
int type);
void noteLongPartialWakelockStart(String name, String historyName, int uid);
+ void noteLongPartialWakelockStartFromSource(String name, String historyName,
+ in WorkSource workSource);
void noteLongPartialWakelockFinish(String name, String historyName, int uid);
+ void noteLongPartialWakelockFinishFromSource(String name, String historyName,
+ in WorkSource workSource);
void noteVibratorOn(int uid, long durationMillis);
void noteVibratorOff(int uid);
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 77cfc2fc..96d3baf 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -411,6 +411,9 @@
mContext.unbindService(mConnection);
mConnection.destroy();
}
+ if (mAfterCompute != null) {
+ mAfterCompute.afterCompute();
+ }
if (DEBUG) {
Log.d(TAG, "Unbinded Resolver Ranker.");
}
@@ -573,7 +576,6 @@
if (DEBUG) {
Log.d(TAG, "Has not found valid ResolverRankerService; Skip Prediction");
}
- return;
} else {
try {
mConnectSignal.await(CONNECTION_COST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index efc9c02..a0be64b 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -89,8 +89,8 @@
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
STATE_IMPORTANT_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -153,7 +153,6 @@
private int mNumActiveServices;
private int mNumStartedServices;
- private int mNumExcessiveWake;
private int mNumExcessiveCpu;
private int mNumCachedKill;
@@ -470,9 +469,23 @@
}
}
- public void addPss(long pss, long uss, boolean always,
+ public void addPss(long pss, long uss, boolean always, int type, long duration,
ArrayMap<String, ProcessStateHolder> pkgList) {
ensureNotDead();
+ switch (type) {
+ case ProcessStats.ADD_PSS_INTERNAL:
+ mStats.mInternalPssCount++;
+ mStats.mInternalPssTime += duration;
+ break;
+ case ProcessStats.ADD_PSS_EXTERNAL:
+ mStats.mExternalPssCount++;
+ mStats.mExternalPssTime += duration;
+ break;
+ case ProcessStats.ADD_PSS_EXTERNAL_SLOW:
+ mStats.mExternalSlowPssCount++;
+ mStats.mExternalSlowPssTime += duration;
+ break;
+ }
if (!always) {
if (mLastPssState == mCurState && SystemClock.uptimeMillis()
< (mLastPssTime+(30*1000))) {
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 96ba2b0..35b2dd2 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -134,6 +134,10 @@
public static final int FLAG_SHUTDOWN = 1<<1;
public static final int FLAG_SYSPROPS = 1<<2;
+ public static final int ADD_PSS_INTERNAL = 0;
+ public static final int ADD_PSS_EXTERNAL = 1;
+ public static final int ADD_PSS_EXTERNAL_SLOW = 2;
+
public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
@@ -158,7 +162,7 @@
};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 23;
+ private static final int PARCEL_VERSION = 24;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -183,6 +187,18 @@
boolean mHasSwappedOutPss;
+ // Count and total time expended doing "quick" pss computations for internal use.
+ public long mInternalPssCount;
+ public long mInternalPssTime;
+
+ // Count and total time expended doing "quick" pss computations due to external requests.
+ public long mExternalPssCount;
+ public long mExternalPssTime;
+
+ // Count and total time expended doing full/slow pss computations due to external requests.
+ public long mExternalSlowPssCount;
+ public long mExternalSlowPssTime;
+
public final SparseMappingTable mTableData = new SparseMappingTable();
public final long[] mSysMemUsageArgs = new long[SYS_MEM_USAGE_COUNT];
@@ -302,6 +318,13 @@
mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime;
+ mInternalPssCount += other.mInternalPssCount;
+ mInternalPssTime += other.mInternalPssTime;
+ mExternalPssCount += other.mExternalPssCount;
+ mExternalPssTime += other.mExternalPssTime;
+ mExternalSlowPssCount += other.mExternalSlowPssCount;
+ mExternalSlowPssTime += other.mExternalSlowPssTime;
+
mHasSwappedOutPss |= other.mHasSwappedOutPss;
}
@@ -500,6 +523,12 @@
buildTimePeriodStartClockStr();
mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
+ mInternalPssCount = 0;
+ mInternalPssTime = 0;
+ mExternalPssCount = 0;
+ mExternalPssTime = 0;
+ mExternalSlowPssCount = 0;
+ mExternalSlowPssTime = 0;
mTableData.reset();
Arrays.fill(mMemFactorDurations, 0);
mSysMemUsage.resetTable();
@@ -760,6 +789,12 @@
out.writeLong(mTimePeriodEndRealtime);
out.writeLong(mTimePeriodStartUptime);
out.writeLong(mTimePeriodEndUptime);
+ out.writeLong(mInternalPssCount);
+ out.writeLong(mInternalPssTime);
+ out.writeLong(mExternalPssCount);
+ out.writeLong(mExternalPssTime);
+ out.writeLong(mExternalSlowPssCount);
+ out.writeLong(mExternalSlowPssTime);
out.writeString(mRuntime);
out.writeInt(mHasSwappedOutPss ? 1 : 0);
out.writeInt(mFlags);
@@ -928,6 +963,12 @@
mTimePeriodEndRealtime = in.readLong();
mTimePeriodStartUptime = in.readLong();
mTimePeriodEndUptime = in.readLong();
+ mInternalPssCount = in.readLong();
+ mInternalPssTime = in.readLong();
+ mExternalPssCount = in.readLong();
+ mExternalPssTime = in.readLong();
+ mExternalSlowPssCount = in.readLong();
+ mExternalSlowPssTime = in.readLong();
mRuntime = in.readString();
mHasSwappedOutPss = in.readInt() != 0;
mFlags = in.readInt();
@@ -1484,9 +1525,31 @@
totalMem.processStateWeight[STATE_SERVICE_RESTARTING], totalMem.totalTime, totalPss,
totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
pw.println();
+ pw.println("PSS collection stats:");
+ pw.print(" Internal: ");
+ pw.print(mInternalPssCount);
+ pw.print("x over ");
+ TimeUtils.formatDuration(mInternalPssTime, pw);
+ pw.println();
+ pw.print(" External: ");
+ pw.print(mExternalPssCount);
+ pw.print("x over ");
+ TimeUtils.formatDuration(mExternalPssTime, pw);
+ pw.println();
+ pw.print(" External Slow: ");
+ pw.print(mExternalSlowPssCount);
+ pw.print("x over ");
+ TimeUtils.formatDuration(mExternalSlowPssTime, pw);
+ pw.println();
+ pw.println();
pw.print(" Start time: ");
pw.print(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimePeriodStartClock));
pw.println();
+ pw.print(" Total uptime: ");
+ TimeUtils.formatDuration(
+ (mRunning ? SystemClock.uptimeMillis() : mTimePeriodEndUptime)
+ - mTimePeriodStartUptime, pw);
+ pw.println();
pw.print(" Total elapsed time: ");
TimeUtils.formatDuration(
(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index a4da6b9c..f9bf373 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -56,6 +56,7 @@
void partiallyUpdateAppWidgetIds(String callingPackage, in int[] appWidgetIds,
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
+ void updateAppWidgetProviderInfo(in ComponentName provider, in String metadataKey);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
String packageName);
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index 71baaf1..9b7383f 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -53,10 +53,8 @@
public static final int THRESHOLD_COLOR_LIGHT = 0xffe0e0e0;
public static final int MAIN_COLOR_LIGHT = 0xffe0e0e0;
- public static final int SECONDARY_COLOR_LIGHT = 0xff9e9e9e;
public static final int THRESHOLD_COLOR_DARK = 0xff212121;
public static final int MAIN_COLOR_DARK = 0xff000000;
- public static final int SECONDARY_COLOR_DARK = 0xff000000;
private final TonalPalette mGreyPalette;
private final ArrayList<TonalPalette> mTonalPalettes;
@@ -211,10 +209,8 @@
}
// Normal colors:
- // best fit + a 2 colors offset
outColorsNormal.setMainColor(mainColor);
- int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
- outColorsNormal.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+ outColorsNormal.setSecondaryColor(mainColor);
// Dark colors:
// Stops at 4th color, only lighter if dark text is supported
@@ -225,9 +221,9 @@
} else {
primaryIndex = Math.min(fitIndex, 3);
}
- secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
- outColorsDark.setMainColor(getColorInt(primaryIndex, h, s, l));
- outColorsDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+ mainColor = getColorInt(primaryIndex, h, s, l);
+ outColorsDark.setMainColor(mainColor);
+ outColorsDark.setSecondaryColor(mainColor);
// Extra Dark:
// Stay close to dark colors until dark text is supported
@@ -238,9 +234,9 @@
} else {
primaryIndex = 2;
}
- secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
- outColorsExtraDark.setMainColor(getColorInt(primaryIndex, h, s, l));
- outColorsExtraDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));
+ mainColor = getColorInt(primaryIndex, h, s, l);
+ outColorsExtraDark.setMainColor(mainColor);
+ outColorsExtraDark.setSecondaryColor(mainColor);
outColorsNormal.setSupportsDarkText(supportsDarkText);
outColorsDark.setSupportsDarkText(supportsDarkText);
@@ -273,11 +269,10 @@
boolean light = inWallpaperColors != null
&& (inWallpaperColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT)
!= 0;
- int innerColor = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
- int outerColor = light ? SECONDARY_COLOR_LIGHT : SECONDARY_COLOR_DARK;
+ final int color = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
- outGradientColors.setMainColor(innerColor);
- outGradientColors.setSecondaryColor(outerColor);
+ outGradientColors.setMainColor(color);
+ outGradientColors.setSecondaryColor(color);
outGradientColors.setSupportsDarkText(light);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index db8fcf6..b8ff9e4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -21,10 +21,13 @@
import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.UidTraffic;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
+import android.net.Uri;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
@@ -46,6 +49,7 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
+import android.provider.Settings;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
@@ -54,6 +58,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.IntArray;
+import android.util.KeyValueListParser;
import android.util.Log;
import android.util.LogWriter;
import android.util.LongSparseArray;
@@ -124,7 +129,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 172 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 173 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS;
@@ -289,12 +294,21 @@
/**
* Update per-freq cpu times for all the uids in {@link #mPendingUids}.
*/
- public void updateProcStateCpuTimes() {
+ public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
final SparseIntArray uidStates;
synchronized (BatteryStatsImpl.this) {
+ if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
+ return;
+ }
if(!initKernelSingleUidTimeReaderLocked()) {
return;
}
+ // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
+ // compute deltas since it might result in mis-attributing cpu times to wrong states.
+ if (mKernelSingleUidTimeReader.hasStaleData()) {
+ mPendingUids.clear();
+ return;
+ }
if (mPendingUids.size() == 0) {
return;
@@ -307,7 +321,6 @@
final int procState = uidStates.valueAt(i);
final int[] isolatedUids;
final Uid u;
- final boolean onBattery;
synchronized (BatteryStatsImpl.this) {
// It's possible that uid no longer exists and any internal references have
// already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
@@ -324,7 +337,6 @@
isolatedUids[j] = u.mChildUids.get(j);
}
}
- onBattery = mOnBatteryInternal;
}
long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
if (isolatedUids != null) {
@@ -335,27 +347,45 @@
}
if (onBattery && cpuTimesMs != null) {
synchronized (BatteryStatsImpl.this) {
- u.addProcStateTimesMs(procState, cpuTimesMs);
- u.addProcStateScreenOffTimesMs(procState, cpuTimesMs);
+ u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
+ u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
}
}
}
}
+ public void copyFromAllUidsCpuTimes() {
+ synchronized (BatteryStatsImpl.this) {
+ copyFromAllUidsCpuTimes(
+ mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
+ }
+ }
+
/**
* When the battery/screen state changes, we don't attribute the cpu times to any process
* but we still need to snapshots of all uids to get correct deltas later on. Since we
* already read this data for updating per-freq cpu times, we can use the same data for
* per-procstate cpu times.
*/
- public void copyFromAllUidsCpuTimes() {
+ public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
synchronized (BatteryStatsImpl.this) {
+ if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
+ return;
+ }
if(!initKernelSingleUidTimeReaderLocked()) {
return;
}
final SparseArray<long[]> allUidCpuFreqTimesMs =
mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
+ // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
+ // compute deltas since it might result in mis-attributing cpu times to wrong states.
+ if (mKernelSingleUidTimeReader.hasStaleData()) {
+ mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
+ mKernelSingleUidTimeReader.markDataAsStale(false);
+ mPendingUids.clear();
+ return;
+ }
for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
final int uid = allUidCpuFreqTimesMs.keyAt(i);
final Uid u = getAvailableUidStatsLocked(mapUid(uid));
@@ -368,7 +398,7 @@
}
final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
uid, cpuTimesMs.clone());
- if (mOnBatteryInternal && deltaTimesMs != null) {
+ if (onBattery && deltaTimesMs != null) {
final int procState;
final int idx = mPendingUids.indexOfKey(uid);
if (idx >= 0) {
@@ -378,8 +408,8 @@
procState = u.mProcessState;
}
if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
- u.addProcStateTimesMs(procState, deltaTimesMs);
- u.addProcStateScreenOffTimesMs(procState, deltaTimesMs);
+ u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
+ u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
}
}
}
@@ -443,8 +473,9 @@
Future<?> scheduleSync(String reason, int flags);
Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
- Future<?> scheduleReadProcStateCpuTimes();
- Future<?> scheduleCopyFromAllUidsCpuTimes();
+ Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
+ Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
+ Future<?> scheduleCpuSyncDueToSettingChange();
}
public Handler mHandler;
@@ -807,6 +838,9 @@
@VisibleForTesting
protected PowerProfile mPowerProfile;
+ @GuardedBy("this")
+ private final Constants mConstants;
+
/*
* Holds a SamplingTimer associated with each Resource Power Manager state and voter,
* recording their times when on-battery (regardless of screen state).
@@ -895,6 +929,7 @@
mHandler = null;
mPlatformIdleStateCallback = null;
mUserInfoProvider = null;
+ mConstants = new Constants(mHandler);
clearHistoryLocked();
}
@@ -1231,12 +1266,10 @@
public long[] mCounts;
public long[] mLoadedCounts;
public long[] mUnpluggedCounts;
- public long[] mPluggedCounts;
private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
mTimeBase = timeBase;
- mPluggedCounts = in.createLongArray();
- mCounts = copyArray(mPluggedCounts, mCounts);
+ mCounts = in.createLongArray();
mLoadedCounts = in.createLongArray();
mUnpluggedCounts = in.createLongArray();
timeBase.add(this);
@@ -1255,17 +1288,16 @@
@Override
public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
- mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
+ mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
}
@Override
public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
- mPluggedCounts = copyArray(mCounts, mPluggedCounts);
}
@Override
public long[] getCountsLocked(int which) {
- long[] val = copyArray(mTimeBase.isRunning() ? mCounts : mPluggedCounts, null);
+ long[] val = copyArray(mCounts, null);
if (which == STATS_SINCE_UNPLUGGED) {
subtract(val, mUnpluggedCounts);
} else if (which != STATS_SINCE_CHARGED) {
@@ -1278,15 +1310,18 @@
public void logState(Printer pw, String prefix) {
pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
+ " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
- + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts)
- + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
+ + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
}
public void addCountLocked(long[] counts) {
+ addCountLocked(counts, mTimeBase.isRunning());
+ }
+
+ public void addCountLocked(long[] counts, boolean isRunning) {
if (counts == null) {
return;
}
- if (mTimeBase.isRunning()) {
+ if (isRunning) {
if (mCounts == null) {
mCounts = new long[counts.length];
}
@@ -1306,7 +1341,6 @@
public void reset(boolean detachIfReset) {
fillArray(mCounts, 0);
fillArray(mLoadedCounts, 0);
- fillArray(mPluggedCounts, 0);
fillArray(mUnpluggedCounts, 0);
if (detachIfReset) {
detach();
@@ -1325,7 +1359,6 @@
mCounts = in.createLongArray();
mLoadedCounts = copyArray(mCounts, mLoadedCounts);
mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
- mPluggedCounts = copyArray(mCounts, mPluggedCounts);
}
public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
@@ -3783,7 +3816,8 @@
+ " and battery is " + (unplugged ? "on" : "off"));
}
updateCpuTimeLocked();
- mExternalSync.scheduleCopyFromAllUidsCpuTimes();
+ mExternalSync.scheduleCopyFromAllUidsCpuTimes(mOnBatteryTimeBase.isRunning(),
+ mOnBatteryScreenOffTimeBase.isRunning());
mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
if (updateOnBatteryTimeBase) {
@@ -4028,18 +4062,17 @@
public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
String tag) {
- if (!isOnBattery()) {
- return;
- }
if (workSource != null) {
for (int i = 0; i < workSource.size(); ++i) {
uid = workSource.get(i);
final String workSourceName = workSource.getName(i);
- BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
- workSourceName != null ? workSourceName : packageName);
- pkg.noteWakeupAlarmLocked(tag);
+ if (isOnBattery()) {
+ BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
+ workSourceName != null ? workSourceName : packageName);
+ pkg.noteWakeupAlarmLocked(tag);
+ }
StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
}
@@ -4050,16 +4083,20 @@
final WorkChain wc = workChains.get(i);
uid = wc.getAttributionUid();
- BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
- pkg.noteWakeupAlarmLocked(tag);
+ if (isOnBattery()) {
+ BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
+ pkg.noteWakeupAlarmLocked(tag);
+ }
// TODO(statsd): Log the full attribution chain here once it's available
StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
}
}
} else {
- BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
- pkg.noteWakeupAlarmLocked(tag);
+ if (isOnBattery()) {
+ BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
+ pkg.noteWakeupAlarmLocked(tag);
+ }
StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
}
}
@@ -4318,6 +4355,34 @@
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
uid = mapUid(uid);
+ noteLongPartialWakeLockStartInternal(name, historyName, uid);
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 1);
+ }
+
+ public void noteLongPartialWakelockStartFromSource(String name, String historyName,
+ WorkSource workSource) {
+ final int N = workSource.size();
+ for (int i = 0; i < N; ++i) {
+ final int uid = mapUid(workSource.get(i));
+ noteLongPartialWakeLockStartInternal(name, historyName, uid);
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 1);
+ }
+
+ final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ if (workChains != null) {
+ for (int i = 0; i < workChains.size(); ++i) {
+ final WorkChain workChain = workChains.get(i);
+ final int uid = workChain.getAttributionUid();
+ noteLongPartialWakeLockStartInternal(name, historyName, uid);
+
+ // TODO(statsd): the Log WorkChain to statds, and not just the uid.
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName,
+ 1);
+ }
+ }
+ }
+
+ private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
if (historyName == null) {
@@ -4329,11 +4394,39 @@
}
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
historyName, uid);
- StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 1);
}
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
uid = mapUid(uid);
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 0);
+ }
+
+ public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
+ WorkSource workSource) {
+ final int N = workSource.size();
+ for (int i = 0; i < N; ++i) {
+ final int uid = mapUid(workSource.get(i));
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 0);
+ }
+
+ final ArrayList<WorkChain> workChains = workSource.getWorkChains();
+ if (workChains != null) {
+ for (int i = 0; i < workChains.size(); ++i) {
+ final WorkChain workChain = workChains.get(i);
+ final int uid = workChain.getAttributionUid();
+
+ noteLongPartialWakeLockFinishInternal(name, historyName, uid);
+
+ // TODO(statsd): the Log WorkChain to statds, and not just the uid.
+ StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName,
+ 0);
+ }
+ }
+ }
+
+ private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
if (historyName == null) {
@@ -4345,7 +4438,6 @@
}
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
historyName, uid);
- StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 0);
}
void aggregateLastWakeupUptimeLocked(long uptimeMs) {
@@ -6590,7 +6682,7 @@
return null;
}
- private void addProcStateTimesMs(int procState, long[] cpuTimesMs) {
+ private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
if (mProcStateTimeMs == null) {
mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
}
@@ -6599,10 +6691,11 @@
mProcStateTimeMs[procState] = new LongSamplingCounterArray(
mBsi.mOnBatteryTimeBase);
}
- mProcStateTimeMs[procState].addCountLocked(cpuTimesMs);
+ mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
}
- private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs) {
+ private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
+ boolean onBatteryScreenOff) {
if (mProcStateScreenOffTimeMs == null) {
mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
}
@@ -6611,7 +6704,7 @@
mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
mBsi.mOnBatteryScreenOffTimeBase);
}
- mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs);
+ mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
}
@Override
@@ -9348,9 +9441,11 @@
if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
- if (mBsi.mPerProcStateCpuTimesAvailable) {
+ if (mBsi.trackPerProcStateCpuTimes()) {
if (mBsi.mPendingUids.size() == 0) {
- mBsi.mExternalSync.scheduleReadProcStateCpuTimes();
+ mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
+ mBsi.mOnBatteryTimeBase.isRunning(),
+ mBsi.mOnBatteryScreenOffTimeBase.isRunning());
}
if (mBsi.mPendingUids.indexOfKey(mUid) < 0
|| ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
@@ -9700,6 +9795,7 @@
mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
mHandler = new MyHandler(handler.getLooper());
+ mConstants = new Constants(mHandler);
mStartCount++;
mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
@@ -9795,6 +9891,7 @@
mDailyFile = null;
mHandler = null;
mExternalSync = null;
+ mConstants = new Constants(mHandler);
clearHistoryLocked();
readFromParcel(p);
mPlatformIdleStateCallback = null;
@@ -12548,6 +12645,78 @@
mShuttingDown = true;
}
+ public boolean trackPerProcStateCpuTimes() {
+ return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
+ }
+
+ public void systemServicesReady(Context context) {
+ mConstants.startObserving(context.getContentResolver());
+ }
+
+ @VisibleForTesting
+ public final class Constants extends ContentObserver {
+ public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
+ = "track_cpu_times_by_proc_state";
+
+ private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
+
+ public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
+
+ private ContentResolver mResolver;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ public Constants(Handler handler) {
+ super(handler);
+ }
+
+ public void startObserving(ContentResolver resolver) {
+ mResolver = resolver;
+ mResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
+ false /* notifyForDescendants */, this);
+ updateConstants();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateConstants();
+ }
+
+ private void updateConstants() {
+ synchronized (BatteryStatsImpl.this) {
+ try {
+ mParser.setString(Settings.Global.getString(mResolver,
+ Settings.Global.BATTERY_STATS_CONSTANTS));
+ } catch (IllegalArgumentException e) {
+ // Failed to parse the settings string, log this and move on
+ // with defaults.
+ Slog.e(TAG, "Bad batterystats settings", e);
+ }
+
+ updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
+ mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
+ DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
+ }
+ }
+
+ private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
+ TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
+ if (isEnabled && !wasEnabled) {
+ mKernelSingleUidTimeReader.markDataAsStale(true);
+ mExternalSync.scheduleCpuSyncDueToSettingChange();
+ }
+ }
+
+ public void dumpLocked(PrintWriter pw) {
+ pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
+ pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
+ }
+ }
+
+ public void dumpConstantsLocked(PrintWriter pw) {
+ mConstants.dumpLocked(pw);
+ }
+
Parcel mPendingWrite = null;
final ReentrantLock mWriteLock = new ReentrantLock();
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index ca635a4..ebeb24c4 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -46,12 +46,14 @@
private final int mCpuFreqsCount;
@GuardedBy("this")
- private final SparseArray<long[]> mLastUidCpuTimeMs = new SparseArray<>();
+ private SparseArray<long[]> mLastUidCpuTimeMs = new SparseArray<>();
@GuardedBy("this")
private int mReadErrorCounter;
@GuardedBy("this")
private boolean mSingleUidCpuTimesAvailable = true;
+ @GuardedBy("this")
+ private boolean mHasStaleData;
private final Injector mInjector;
@@ -166,6 +168,30 @@
return deltaTimesMs;
}
+ public void markDataAsStale(boolean hasStaleData) {
+ synchronized (this) {
+ mHasStaleData = hasStaleData;
+ }
+ }
+
+ public boolean hasStaleData() {
+ synchronized (this) {
+ return mHasStaleData;
+ }
+ }
+
+ public void setAllUidsCpuTimesMs(SparseArray<long[]> allUidsCpuTimesMs) {
+ synchronized (this) {
+ mLastUidCpuTimeMs.clear();
+ for (int i = allUidsCpuTimesMs.size() - 1; i >= 0; --i) {
+ final long[] cpuTimesMs = allUidsCpuTimesMs.valueAt(i);
+ if (cpuTimesMs != null) {
+ mLastUidCpuTimeMs.put(allUidsCpuTimesMs.keyAt(i), cpuTimesMs.clone());
+ }
+ }
+ }
+ }
+
public void removeUid(int uid) {
synchronized (this) {
mLastUidCpuTimeMs.delete(uid);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 2be6212..c5fe4cb 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -650,7 +650,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 5fddfba..95bc352 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -101,7 +101,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
@@ -194,8 +193,6 @@
// View added at runtime to draw under the status bar area
private View mStatusGuard;
- // View added at runtime to draw under the navigation bar area
- private View mNavigationGuard;
private final ColorViewState mStatusColorViewState =
new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
@@ -1002,7 +999,6 @@
mFrameOffsets.set(insets.getSystemWindowInsets());
insets = updateColorViews(insets, true /* animate */);
insets = updateStatusGuard(insets);
- insets = updateNavigationGuard(insets);
if (getForeground() != null) {
drawableChanged();
}
@@ -1062,7 +1058,10 @@
WindowManager.LayoutParams attrs = mWindow.getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
- if (!mWindow.mIsFloating) {
+ // IME is an exceptional floating window that requires color view.
+ final boolean isImeWindow =
+ mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+ if (!mWindow.mIsFloating || isImeWindow) {
boolean disallowAnimate = !isLaidOut();
disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
& FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -1363,7 +1362,7 @@
if (mStatusGuard == null) {
mStatusGuard = new View(mContext);
mStatusGuard.setBackgroundColor(mContext.getColor(
- R.color.input_method_navigation_guard));
+ R.color.decor_view_status_guard));
addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
new LayoutParams(LayoutParams.MATCH_PARENT,
mlp.topMargin, Gravity.START | Gravity.TOP));
@@ -1407,51 +1406,6 @@
return insets;
}
- private WindowInsets updateNavigationGuard(WindowInsets insets) {
- // IME windows lay out below the nav bar, but the content view must not (for back compat)
- // Only make this adjustment if the window is not requesting layout in overscan
- if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
- && (mWindow.getAttributes().flags & FLAG_LAYOUT_IN_OVERSCAN) == 0) {
- // prevent the content view from including the nav bar height
- if (mWindow.mContentParent != null) {
- if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
- MarginLayoutParams mlp =
- (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
- mlp.bottomMargin = insets.getSystemWindowInsetBottom();
- mWindow.mContentParent.setLayoutParams(mlp);
- }
- }
- // position the navigation guard view, creating it if necessary
- if (mNavigationGuard == null) {
- mNavigationGuard = new View(mContext);
- mNavigationGuard.setBackgroundColor(mContext.getColor(
- R.color.input_method_navigation_guard));
- addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
- new LayoutParams(LayoutParams.MATCH_PARENT,
- insets.getSystemWindowInsetBottom(),
- Gravity.START | Gravity.BOTTOM));
- } else {
- LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
- lp.height = insets.getSystemWindowInsetBottom();
- mNavigationGuard.setLayoutParams(lp);
- }
- updateNavigationGuardColor();
- insets = insets.consumeSystemWindowInsets(
- false, false, false, true /* bottom */);
- }
- return insets;
- }
-
- void updateNavigationGuardColor() {
- if (mNavigationGuard != null) {
- // Make navigation bar guard invisible if the transparent color is specified.
- // Only TRANSPARENT is sufficient for hiding the navigation bar if the no software
- // keyboard is shown by IMS.
- mNavigationGuard.setVisibility(mWindow.getNavigationBarColor() == Color.TRANSPARENT ?
- View.INVISIBLE : View.VISIBLE);
- }
- }
-
/**
* Overrides the view outline when the activity enters picture-in-picture to ensure that it has
* an opaque shadow even if the window background is completely transparent. This only applies
@@ -2103,7 +2057,7 @@
for (int i = getChildCount() - 1; i >= 0; i--) {
View v = getChildAt(i);
if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
- && v != mStatusGuard && v != mNavigationGuard) {
+ && v != mStatusGuard) {
removeViewAt(i);
}
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index b13560c..e8ee29d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3807,7 +3807,6 @@
mForcedNavigationBarColor = true;
if (mDecor != null) {
mDecor.updateColorViews(null, false /* animate */);
- mDecor.updateNavigationGuardColor();
}
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 862288b..4e7df28 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -66,6 +66,7 @@
void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
KeyStoreRecoveryData getRecoveryData(in byte[] account);
byte[] generateAndStoreKey(String alias);
+ void removeKey(String alias);
void setSnapshotCreatedPendingIntent(in PendingIntent intent);
Map getRecoverySnapshotVersions();
void setServerParameters(long serverParameters);
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 792f921..20f05e6 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -20,17 +20,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
+import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Pools;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -41,7 +36,6 @@
import android.widget.RemoteViews;
import com.android.internal.R;
-import com.android.internal.util.NotificationColorUtil;
import java.util.ArrayList;
import java.util.List;
@@ -60,12 +54,12 @@
private int mLayoutColor;
private CharSequence mAvatarName = "";
private Icon mAvatarIcon;
- private ColorFilter mMessageBackgroundFilter;
private int mTextColor;
private List<MessagingMessage> mMessages;
private ArrayList<MessagingMessage> mAddedMessages = new ArrayList<>();
private boolean mFirstLayout;
private boolean mIsHidingAnimated;
+ private boolean mNeedsGeneratedAvatar;
public MessagingGroup(@NonNull Context context) {
super(context);
@@ -94,27 +88,19 @@
mAvatarView = findViewById(R.id.message_icon);
}
- public void setSender(CharSequence sender) {
- if (sender == null) {
- mAvatarView.setVisibility(GONE);
- mSenderName.setVisibility(GONE);
- setGravity(Gravity.END);
- mMessageBackgroundFilter = new PorterDuffColorFilter(mLayoutColor,
- PorterDuff.Mode.SRC_ATOP);
- mTextColor = NotificationColorUtil.isColorLight(mLayoutColor) ? getNormalTextColor()
- : Color.WHITE;
- } else {
- mSenderName.setText(sender);
- mAvatarView.setVisibility(VISIBLE);
- mSenderName.setVisibility(VISIBLE);
- setGravity(Gravity.START);
- mMessageBackgroundFilter = null;
- mTextColor = getNormalTextColor();
+ public void setSender(Notification.Person sender) {
+ mSenderName.setText(sender.getName());
+ mNeedsGeneratedAvatar = sender.getIcon() == null;
+ if (!mNeedsGeneratedAvatar) {
+ setAvatar(sender.getIcon());
}
+ mAvatarView.setVisibility(VISIBLE);
+ mSenderName.setVisibility(VISIBLE);
+ mTextColor = getNormalTextColor();
}
private int getNormalTextColor() {
- return mContext.getColor(R.color.notification_primary_text_color_light);
+ return mContext.getColor(R.color.notification_secondary_text_color_light);
}
public void setAvatar(Icon icon) {
@@ -207,10 +193,6 @@
return mSenderName.getText();
}
- public void setSenderVisible(boolean visible) {
- mSenderName.setVisibility(visible ? VISIBLE : GONE);
- }
-
public static void dropCache() {
sInstancePool = new Pools.SynchronizedPool<>(10);
}
@@ -317,12 +299,6 @@
mMessageContainer.removeView(message);
mMessageContainer.addView(message, messageIndex);
}
- // Let's make sure the message color is correct
- Drawable targetDrawable = message.getBackground();
-
- if (targetDrawable != null) {
- targetDrawable.mutate().setColorFilter(mMessageBackgroundFilter);
- }
message.setTextColor(mTextColor);
}
mMessages = group;
@@ -390,4 +366,8 @@
public MessagingLinearLayout getMessageContainer() {
return mMessageContainer;
}
+
+ public boolean needsGeneratedAvatar() {
+ return mNeedsGeneratedAvatar;
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 2acdc01..834c93a 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -69,7 +69,6 @@
private List<MessagingMessage> mMessages = new ArrayList<>();
private List<MessagingMessage> mHistoricMessages = new ArrayList<>();
private MessagingLinearLayout mMessagingLinearLayout;
- private View mContractedMessage;
private boolean mShowHistoricMessages;
private ArrayList<MessagingGroup> mGroups = new ArrayList<>();
private TextView mTitleView;
@@ -81,6 +80,7 @@
private Icon mLargeIcon;
private boolean mIsOneToOne;
private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
+ private Notification.Person mUser;
public MessagingLayout(@NonNull Context context) {
super(context);
@@ -129,6 +129,7 @@
Parcelable[] histMessages = extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES);
List<Notification.MessagingStyle.Message> newHistoricMessages
= Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
+ setUser(extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON));
mConversationTitle = null;
TextView headerText = findViewById(R.id.header_text);
if (headerText != null) {
@@ -152,7 +153,6 @@
mMessages = messages;
mHistoricMessages = historicMessages;
- updateContractedMessage();
updateHistoricMessageVisibility();
updateTitleAndNamesDisplay();
}
@@ -163,12 +163,10 @@
for (int i = 0; i < mGroups.size(); i++) {
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
continue;
}
- boolean visible = !mIsOneToOne;
- group.setSenderVisible(visible);
- if ((visible || mLargeIcon == null) && !uniqueNames.containsKey(senderName)) {
+ if (!uniqueNames.containsKey(senderName)) {
char c = senderName.charAt(0);
if (uniqueCharacters.containsKey(c)) {
// this character was already used, lets make it more unique. We first need to
@@ -192,7 +190,8 @@
// Let's now set the avatars
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName) || (mIsOneToOne && mLargeIcon != null)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)
+ || (mIsOneToOne && mLargeIcon != null)) {
continue;
}
String symbol = uniqueNames.get(senderName);
@@ -207,7 +206,7 @@
// Let's now set the avatars
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
continue;
}
if (mIsOneToOne && mLargeIcon != null) {
@@ -234,7 +233,7 @@
canvas.drawCircle(radius, radius, radius, mPaint);
boolean needDarkText = ColorUtils.calculateLuminance(color) > 0.5f;
mTextPaint.setColor(needDarkText ? Color.BLACK : Color.WHITE);
- mTextPaint.setTextSize(symbol.length() == 1 ? mAvatarSize * 0.75f : mAvatarSize * 0.4f);
+ mTextPaint.setTextSize(symbol.length() == 1 ? mAvatarSize * 0.5f : mAvatarSize * 0.3f);
int yPos = (int) (radius - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)) ;
canvas.drawText(symbol, radius, yPos, mTextPaint);
return Icon.createWithBitmap(bitmap);
@@ -270,11 +269,15 @@
mIsOneToOne = oneToOne;
}
+ public void setUser(Notification.Person user) {
+ mUser = user;
+ }
+
private void addMessagesToGroups(List<MessagingMessage> historicMessages,
List<MessagingMessage> messages) {
// Let's first find our groups!
List<List<MessagingMessage>> groups = new ArrayList<>();
- List<CharSequence> senders = new ArrayList<>();
+ List<Notification.Person> senders = new ArrayList<>();
// Lets first find the groups
findGroups(historicMessages, messages, groups, senders);
@@ -283,7 +286,8 @@
createGroupViews(groups, senders);
}
- private void createGroupViews(List<List<MessagingMessage>> groups, List<CharSequence> senders) {
+ private void createGroupViews(List<List<MessagingMessage>> groups,
+ List<Notification.Person> senders) {
mGroups.clear();
for (int groupIndex = 0; groupIndex < groups.size(); groupIndex++) {
List<MessagingMessage> group = groups.get(groupIndex);
@@ -314,8 +318,8 @@
private void findGroups(List<MessagingMessage> historicMessages,
List<MessagingMessage> messages, List<List<MessagingMessage>> groups,
- List<CharSequence> senders) {
- CharSequence currentSender = null;
+ List<Notification.Person> senders) {
+ CharSequence currentSenderKey = null;
List<MessagingMessage> currentGroup = null;
int histSize = historicMessages.size();
for (int i = 0; i < histSize + messages.size(); i++) {
@@ -326,35 +330,23 @@
message = messages.get(i - histSize);
}
boolean isNewGroup = currentGroup == null;
- CharSequence sender = message.getMessage().getSender();
- isNewGroup |= !TextUtils.equals(sender, currentSender);
+ Notification.Person sender = message.getMessage().getSenderPerson();
+ CharSequence key = sender == null ? null
+ : sender.getKey() == null ? sender.getName() : sender.getKey();
+ isNewGroup |= !TextUtils.equals(key, currentSenderKey);
if (isNewGroup) {
currentGroup = new ArrayList<>();
groups.add(currentGroup);
+ if (sender == null) {
+ sender = mUser;
+ }
senders.add(sender);
- currentSender = sender;
+ currentSenderKey = key;
}
currentGroup.add(message);
}
}
- private void updateContractedMessage() {
- for (int i = mMessages.size() - 1; i >= 0; i--) {
- MessagingMessage m = mMessages.get(i);
- // Incoming messages have a non-empty sender.
- if (!TextUtils.isEmpty(m.getMessage().getSender())) {
- mContractedMessage = m;
- return;
- }
- }
- if (!mMessages.isEmpty()) {
- // No incoming messages, fall back to outgoing message
- mContractedMessage = mMessages.get(mMessages.size() - 1);
- return;
- }
- mContractedMessage = null;
- }
-
/**
* Creates new messages, reusing existing ones if they are available.
*
@@ -430,10 +422,6 @@
}
}
- public View getContractedMessage() {
- return mContractedMessage;
- }
-
public MessagingLinearLayout getMessagingLinearLayout() {
return mMessagingLinearLayout;
}
diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java
index 7abc76a..408a4e9 100644
--- a/core/java/com/android/internal/widget/RecyclerView.java
+++ b/core/java/com/android/internal/widget/RecyclerView.java
@@ -9556,7 +9556,7 @@
if (vScroll == 0 && hScroll == 0) {
return false;
}
- mRecyclerView.scrollBy(hScroll, vScroll);
+ mRecyclerView.smoothScrollBy(hScroll, vScroll);
return true;
}
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index de2b7c3..4257c98 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -12,21 +12,62 @@
static jmethodID gInputStream_readMethodID;
static jmethodID gInputStream_skipMethodID;
+// FIXME: Share with ByteBufferStreamAdaptor.cpp?
+static JNIEnv* get_env_or_die(JavaVM* jvm) {
+ JNIEnv* env;
+ if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", jvm);
+ }
+ return env;
+}
+
/**
* Wrapper for a Java InputStream.
*/
class JavaInputStreamAdaptor : public SkStream {
+ JavaInputStreamAdaptor(JavaVM* jvm, jobject js, jbyteArray ar, jint capacity,
+ bool swallowExceptions)
+ : fJvm(jvm)
+ , fJavaInputStream(js)
+ , fJavaByteArray(ar)
+ , fCapacity(capacity)
+ , fBytesRead(0)
+ , fIsAtEnd(false)
+ , fSwallowExceptions(swallowExceptions) {}
+
public:
- JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
- : fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) {
- SkASSERT(ar);
- fCapacity = env->GetArrayLength(ar);
- SkASSERT(fCapacity > 0);
- fBytesRead = 0;
- fIsAtEnd = false;
+ static JavaInputStreamAdaptor* Create(JNIEnv* env, jobject js, jbyteArray ar,
+ bool swallowExceptions) {
+ JavaVM* jvm;
+ LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&jvm) != JNI_OK);
+
+ js = env->NewGlobalRef(js);
+ if (!js) {
+ return nullptr;
+ }
+
+ ar = (jbyteArray) env->NewGlobalRef(ar);
+ if (!ar) {
+ env->DeleteGlobalRef(js);
+ return nullptr;
+ }
+
+ jint capacity = env->GetArrayLength(ar);
+ return new JavaInputStreamAdaptor(jvm, js, ar, capacity, swallowExceptions);
}
- virtual size_t read(void* buffer, size_t size) {
+ ~JavaInputStreamAdaptor() override {
+ auto* env = get_env_or_die(fJvm);
+ env->DeleteGlobalRef(fJavaInputStream);
+ env->DeleteGlobalRef(fJavaByteArray);
+ }
+
+ size_t read(void* buffer, size_t size) override {
+ auto* env = get_env_or_die(fJvm);
+ if (!fSwallowExceptions && checkException(env)) {
+ // Just in case the caller did not clear from a previous exception.
+ return 0;
+ }
if (NULL == buffer) {
if (0 == size) {
return 0;
@@ -37,10 +78,10 @@
*/
size_t amountSkipped = 0;
do {
- size_t amount = this->doSkip(size - amountSkipped);
+ size_t amount = this->doSkip(size - amountSkipped, env);
if (0 == amount) {
char tmp;
- amount = this->doRead(&tmp, 1);
+ amount = this->doRead(&tmp, 1, env);
if (0 == amount) {
// if read returned 0, we're at EOF
fIsAtEnd = true;
@@ -52,16 +93,13 @@
return amountSkipped;
}
}
- return this->doRead(buffer, size);
+ return this->doRead(buffer, size, env);
}
- virtual bool isAtEnd() const {
- return fIsAtEnd;
- }
+ bool isAtEnd() const override { return fIsAtEnd; }
private:
- size_t doRead(void* buffer, size_t size) {
- JNIEnv* env = fEnv;
+ size_t doRead(void* buffer, size_t size, JNIEnv* env) {
size_t bytesRead = 0;
// read the bytes
do {
@@ -76,13 +114,9 @@
jint n = env->CallIntMethod(fJavaInputStream,
gInputStream_readMethodID, fJavaByteArray, 0, requested);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
+ if (checkException(env)) {
SkDebugf("---- read threw an exception\n");
- // Consider the stream to be at the end, since there was an error.
- fIsAtEnd = true;
- return 0;
+ return bytesRead;
}
if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
@@ -92,14 +126,9 @@
env->GetByteArrayRegion(fJavaByteArray, 0, n,
reinterpret_cast<jbyte*>(buffer));
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
+ if (checkException(env)) {
SkDebugf("---- read:GetByteArrayRegion threw an exception\n");
- // The error was not with the stream itself, but consider it to be at the
- // end, since we do not have a way to recover.
- fIsAtEnd = true;
- return 0;
+ return bytesRead;
}
buffer = (void*)((char*)buffer + n);
@@ -111,14 +140,10 @@
return bytesRead;
}
- size_t doSkip(size_t size) {
- JNIEnv* env = fEnv;
-
+ size_t doSkip(size_t size, JNIEnv* env) {
jlong skipped = env->CallLongMethod(fJavaInputStream,
gInputStream_skipMethodID, (jlong)size);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
+ if (checkException(env)) {
SkDebugf("------- skip threw an exception\n");
return 0;
}
@@ -129,20 +154,37 @@
return (size_t)skipped;
}
- JNIEnv* fEnv;
- jobject fJavaInputStream; // the caller owns this object
- jbyteArray fJavaByteArray; // the caller owns this object
- jint fCapacity;
+ bool checkException(JNIEnv* env) {
+ if (!env->ExceptionCheck()) {
+ return false;
+ }
+
+ env->ExceptionDescribe();
+ if (fSwallowExceptions) {
+ env->ExceptionClear();
+ }
+
+ // There is no way to recover from the error, so consider the stream
+ // to be at the end.
+ fIsAtEnd = true;
+
+ return true;
+ }
+
+ JavaVM* fJvm;
+ jobject fJavaInputStream;
+ jbyteArray fJavaByteArray;
+ const jint fCapacity;
size_t fBytesRead;
bool fIsAtEnd;
+ const bool fSwallowExceptions;
};
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage) {
- return new JavaInputStreamAdaptor(env, stream, storage);
+SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage,
+ bool swallowExceptions) {
+ return JavaInputStreamAdaptor::Create(env, stream, storage, swallowExceptions);
}
-
static SkMemoryStream* adaptor_to_mem_stream(SkStream* stream) {
SkASSERT(stream != NULL);
size_t bufferSize = 4096;
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
index 56cba51..fccd471 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
@@ -16,13 +16,16 @@
* @param stream Pointer to Java InputStream.
* @param storage Java byte array for retrieving data from the
* Java InputStream.
+ * @param swallowExceptions Whether to call ExceptionClear() after
+ * an Exception is thrown. If false, it is up to the client to
+ * clear or propagate the exception.
* @return SkStream Simple subclass of SkStream which supports its
* basic methods like reading. Only valid until the calling
* function returns, since the Java InputStream is not managed
* by the SkStream.
*/
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage);
+SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage,
+ bool swallowExceptions = true);
/**
* Copy a Java InputStream. The result will be rewindable.
@@ -33,10 +36,8 @@
* @return SkStreamRewindable The data in stream will be copied
* to a new SkStreamRewindable.
*/
-SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream,
- jbyteArray storage);
+SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, jbyteArray storage);
-SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage);
+SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage);
#endif // _ANDROID_GRAPHICS_CREATE_JAVA_OUTPUT_STREAM_ADAPTOR_H_
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index bacab2a..ec03f82 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -15,7 +15,9 @@
*/
#include "Bitmap.h"
+#include "BitmapFactory.h"
#include "ByteBufferStreamAdaptor.h"
+#include "CreateJavaOutputStreamAdaptor.h"
#include "GraphicsJNI.h"
#include "NinePatchPeeker.h"
#include "Utils.h"
@@ -26,10 +28,12 @@
#include <SkAndroidCodec.h>
#include <SkEncodedImageFormat.h>
+#include <SkFrontBufferedStream.h>
#include <SkStream.h>
#include <androidfw/Asset.h>
#include <jni.h>
+#include <sys/stat.h>
using namespace android;
@@ -42,7 +46,7 @@
static jmethodID gPoint_constructorMethodID;
static jmethodID gIncomplete_constructorMethodID;
static jmethodID gCorrupt_constructorMethodID;
-static jmethodID gCallback_onExceptionMethodID;
+static jmethodID gCallback_onPartialImageMethodID;
static jmethodID gPostProcess_postProcessMethodID;
static jmethodID gCanvas_constructorMethodID;
static jmethodID gCanvas_releaseMethodID;
@@ -69,15 +73,15 @@
static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream) {
if (!stream.get()) {
- return nullObjectReturn("Failed to create a stream");
+ doThrowIOE(env, "Failed to create a stream");
+ return nullptr;
}
std::unique_ptr<ImageDecoder> decoder(new ImageDecoder);
decoder->mCodec = SkAndroidCodec::MakeFromStream(std::move(stream), &decoder->mPeeker);
if (!decoder->mCodec.get()) {
- // FIXME: Add an error code to SkAndroidCodec::MakeFromStream, like
- // SkCodec? Then this can print a more informative error message.
- // (Or we can print one from within SkCodec.)
- ALOGE("Failed to create an SkCodec");
+ // FIXME: (b/71578461) Use the error message from
+ // SkCodec::MakeFromStream to report a more informative error message.
+ doThrowIOE(env, "Failed to create an SkCodec");
return nullptr;
}
@@ -88,7 +92,52 @@
reinterpret_cast<jlong>(decoder.release()), width, height);
}
-static jobject ImageDecoder_nCreate(JNIEnv* env, jobject /*clazz*/, jlong assetPtr) {
+static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
+ jobject fileDescriptor) {
+ int descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
+
+ struct stat fdStat;
+ if (fstat(descriptor, &fdStat) == -1) {
+ doThrowIOE(env, "broken file descriptor; fstat returned -1");
+ return nullptr;
+ }
+
+ int dupDescriptor = dup(descriptor);
+ FILE* file = fdopen(dupDescriptor, "r");
+ if (file == NULL) {
+ close(dupDescriptor);
+ doThrowIOE(env, "Could not open file");
+ return nullptr;
+ }
+ std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file));
+
+ if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
+ return native_create(env, std::move(fileStream));
+ }
+
+ // FIXME: This allows us to pretend the current location is the beginning,
+ // but it would be better if SkFILEStream allowed treating its starting
+ // point as the beginning.
+ std::unique_ptr<SkStream> stream(SkFrontBufferedStream::Make(std::move(fileStream),
+ SkCodec::MinBufferedBytesNeeded()));
+ return native_create(env, std::move(stream));
+}
+
+static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/,
+ jobject is, jbyteArray storage) {
+ std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage, false));
+
+ if (!stream.get()) {
+ doThrowIOE(env, "Failed to create stream!");
+ return nullptr;
+ }
+ std::unique_ptr<SkStream> bufferedStream(
+ SkFrontBufferedStream::Make(std::move(stream),
+ SkCodec::MinBufferedBytesNeeded()));
+ return native_create(env, std::move(bufferedStream));
+}
+
+static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr) {
Asset* asset = reinterpret_cast<Asset*>(assetPtr);
std::unique_ptr<SkStream> stream(new AssetStreamAdaptor(asset));
return native_create(env, std::move(stream));
@@ -99,6 +148,7 @@
std::unique_ptr<SkStream> stream = CreateByteBufferStreamAdaptor(env, jbyteBuffer,
initialPosition, limit);
if (!stream) {
+ doThrowIOE(env, "Failed to read ByteBuffer");
return nullptr;
}
return native_create(env, std::move(stream));
@@ -114,6 +164,7 @@
return codec->getEncodedFormat() == SkEncodedImageFormat::kWEBP;
}
+// This method should never return null. Instead, it should throw an exception.
static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
jobject jcallback, jobject jpostProcess,
jint desiredWidth, jint desiredHeight, jobject jsubset,
@@ -165,7 +216,8 @@
case kOpaque_SkAlphaType:
break;
case kUnknown_SkAlphaType:
- return nullObjectReturn("Unknown alpha type");
+ doThrowIOE(env, "Unknown alpha type");
+ return nullptr;
}
SkColorType colorType = kN32_SkColorType;
@@ -200,7 +252,8 @@
bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType);
}
if (!bm.setInfo(bitmapInfo)) {
- return nullObjectReturn("Failed to setInfo properly");
+ doThrowIOE(env, "Failed to setInfo properly");
+ return nullptr;
}
sk_sp<Bitmap> nativeBitmap;
@@ -213,37 +266,53 @@
nativeBitmap = Bitmap::allocateHeapBitmap(&bm);
}
if (!nativeBitmap) {
- ALOGE("OOM allocating Bitmap with dimensions %i x %i",
- decodeInfo.width(), decodeInfo.height());
- doThrowOOME(env);
+ SkString msg;
+ msg.printf("OOM allocating Bitmap with dimensions %i x %i",
+ decodeInfo.width(), decodeInfo.height());
+ doThrowOOME(env, msg.c_str());
return nullptr;
}
- jobject jexception = nullptr;
SkAndroidCodec::AndroidOptions options;
options.fSampleSize = sampleSize;
auto result = codec->getAndroidPixels(decodeInfo, bm.getPixels(), bm.rowBytes(), &options);
+ jthrowable jexception = env->ExceptionOccurred();
+ if (jexception) {
+ env->ExceptionClear();
+ }
switch (result) {
case SkCodec::kSuccess:
+ // Ignore the exception, since the decode was successful anyway.
+ jexception = nullptr;
break;
case SkCodec::kIncompleteInput:
- if (jcallback) {
- jexception = env->NewObject(gIncomplete_class, gIncomplete_constructorMethodID);
+ if (jcallback && !jexception) {
+ jexception = (jthrowable) env->NewObject(gIncomplete_class,
+ gIncomplete_constructorMethodID);
}
break;
case SkCodec::kErrorInInput:
- if (jcallback) {
- jexception = env->NewObject(gCorrupt_class, gCorrupt_constructorMethodID);
+ if (jcallback && !jexception) {
+ jexception = (jthrowable) env->NewObject(gCorrupt_class,
+ gCorrupt_constructorMethodID);
}
break;
default:
- ALOGE("getPixels failed with error %i", result);
+ SkString msg;
+ msg.printf("getPixels failed with error %i", result);
+ doThrowIOE(env, msg.c_str());
return nullptr;
}
if (jexception) {
- if (!env->CallBooleanMethod(jcallback, gCallback_onExceptionMethodID, jexception) ||
- env->ExceptionCheck()) {
+ bool throwException = !env->CallBooleanMethod(jcallback, gCallback_onPartialImageMethodID,
+ jexception);
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ if (throwException) {
+ env->Throw(jexception);
return nullptr;
}
}
@@ -268,7 +337,8 @@
size_t ninePatchArraySize = decoder->mPeeker.mPatch->serializedSize();
ninePatchChunk = env->NewByteArray(ninePatchArraySize);
if (ninePatchChunk == nullptr) {
- return nullObjectReturn("ninePatchChunk == null");
+ doThrowOOME(env, "Failed to allocate nine patch chunk.");
+ return nullptr;
}
env->SetByteArrayRegion(ninePatchChunk, 0, decoder->mPeeker.mPatchSize,
@@ -278,7 +348,8 @@
if (decoder->mPeeker.mHasInsets) {
ninePatchInsets = decoder->mPeeker.createNinePatchInsets(env, 1.0f);
if (ninePatchInsets == nullptr) {
- return nullObjectReturn("nine patch insets == null");
+ doThrowOOME(env, "Failed to allocate nine patch insets.");
+ return nullptr;
}
}
}
@@ -303,7 +374,8 @@
SkImageInfo scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
SkBitmap scaledBm;
if (!scaledBm.setInfo(scaledInfo)) {
- nullObjectReturn("Failed scaled setInfo");
+ doThrowIOE(env, "Failed scaled setInfo");
+ return nullptr;
}
sk_sp<Bitmap> scaledPixelRef;
@@ -313,9 +385,10 @@
scaledPixelRef = Bitmap::allocateHeapBitmap(&scaledBm);
}
if (!scaledPixelRef) {
- ALOGE("OOM allocating scaled Bitmap with dimensions %i x %i",
- desiredWidth, desiredHeight);
- doThrowOOME(env);
+ SkString msg;
+ msg.printf("OOM allocating scaled Bitmap with dimensions %i x %i",
+ desiredWidth, desiredHeight);
+ doThrowOOME(env, msg.c_str());
return nullptr;
}
@@ -334,13 +407,11 @@
if (jpostProcess) {
std::unique_ptr<Canvas> canvas(Canvas::create_canvas(bm));
- if (!canvas) {
- return nullObjectReturn("Failed to create Canvas for PostProcess!");
- }
jobject jcanvas = env->NewObject(gCanvas_class, gCanvas_constructorMethodID,
reinterpret_cast<jlong>(canvas.get()));
if (!jcanvas) {
- return nullObjectReturn("Failed to create Java Canvas for PostProcess!");
+ doThrowOOME(env, "Failed to create Java Canvas for PostProcess!");
+ return nullptr;
}
// jcanvas will now own canvas.
canvas.release();
@@ -368,15 +439,17 @@
newAlphaType = kOpaque_SkAlphaType;
break;
default:
- ALOGE("invalid return from postProcess: %i", pixelFormat);
- doThrowIAE(env);
+ SkString msg;
+ msg.printf("invalid return from postProcess: %i", pixelFormat);
+ doThrowIAE(env, msg.c_str());
return nullptr;
}
if (newAlphaType != bm.alphaType()) {
if (!bm.setAlphaType(newAlphaType)) {
- ALOGE("incompatible return from postProcess: %i", pixelFormat);
- doThrowIAE(env);
+ SkString msg;
+ msg.printf("incompatible return from postProcess: %i", pixelFormat);
+ doThrowIAE(env, msg.c_str());
return nullptr;
}
nativeBitmap->setAlphaType(newAlphaType);
@@ -405,7 +478,8 @@
ninePatchChunk, ninePatchInsets);
}
if (allocator == ImageDecoder::kHardware_Allocator) {
- return nullObjectReturn("failed to allocate hardware Bitmap!");
+ doThrowOOME(env, "failed to allocate hardware Bitmap!");
+ return nullptr;
}
// If we failed to create a hardware bitmap, go ahead and create a
// software one.
@@ -430,19 +504,27 @@
decoder->mPeeker.getPadding(env, outPadding);
}
-static void ImageDecoder_nRecycle(JNIEnv* /*env*/, jobject /*clazz*/, jlong nativePtr) {
+static void ImageDecoder_nClose(JNIEnv* /*env*/, jobject /*clazz*/, jlong nativePtr) {
delete reinterpret_cast<ImageDecoder*>(nativePtr);
}
+static jstring ImageDecoder_nGetMimeType(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
+ return encodedFormatToString(env, decoder->mCodec->getEncodedFormat());
+}
+
static const JNINativeMethod gImageDecoderMethods[] = {
- { "nCreate", "(J)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreate },
+ { "nCreate", "(J)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateAsset },
{ "nCreate", "(Ljava/nio/ByteBuffer;II)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer },
{ "nCreate", "([BII)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
- { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder$OnExceptionListener;Landroid/graphics/PostProcess;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
+ { "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/PostProcess;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
(void*) ImageDecoder_nDecodeBitmap },
{ "nGetSampledSize","(JI)Landroid/graphics/Point;", (void*) ImageDecoder_nGetSampledSize },
{ "nGetPadding", "(JLandroid/graphics/Rect;)V", (void*) ImageDecoder_nGetPadding },
- { "nRecycle", "(J)V", (void*) ImageDecoder_nRecycle},
+ { "nClose", "(J)V", (void*) ImageDecoder_nClose},
+ { "nGetMimeType", "(J)Ljava/lang/String;", (void*) ImageDecoder_nGetMimeType },
};
int register_android_graphics_ImageDecoder(JNIEnv* env) {
@@ -458,8 +540,8 @@
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$OnExceptionListener");
- gCallback_onExceptionMethodID = GetMethodIDOrDie(env, callback_class, "onException", "(Ljava/lang/Exception;)Z");
+ jclass callback_class = FindClassOrDie(env, "android/graphics/ImageDecoder$OnPartialImageListener");
+ gCallback_onPartialImageMethodID = GetMethodIDOrDie(env, callback_class, "onPartialImage", "(Ljava/io/IOException;)Z");
jclass postProcess_class = FindClassOrDie(env, "android/graphics/PostProcess");
gPostProcess_postProcessMethodID = GetMethodIDOrDie(env, postProcess_class, "postProcess", "(Landroid/graphics/Canvas;II)I");
diff --git a/core/proto/android/app/activitymanager.proto b/core/proto/android/app/activitymanager.proto
index 7385050..3412a32 100644
--- a/core/proto/android/app/activitymanager.proto
+++ b/core/proto/android/app/activitymanager.proto
@@ -38,29 +38,29 @@
PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 300;
// Process is hosting a foreground service.
PROCESS_STATE_FOREGROUND_SERVICE = 400;
- // Same as PROCESS_STATE_TOP but while device is sleeping.
- PROCESS_STATE_TOP_SLEEPING = 500;
// Process is important to the user, and something they are aware of.
- PROCESS_STATE_IMPORTANT_FOREGROUND = 600;
+ PROCESS_STATE_IMPORTANT_FOREGROUND = 500;
// Process is important to the user, but not something they are aware of.
- PROCESS_STATE_IMPORTANT_BACKGROUND = 700;
+ PROCESS_STATE_IMPORTANT_BACKGROUND = 600;
// Process is in the background transient so we will try to keep running.
- PROCESS_STATE_TRANSIENT_BACKGROUND = 800;
+ PROCESS_STATE_TRANSIENT_BACKGROUND = 700;
// Process is in the background running a backup/restore operation.
- PROCESS_STATE_BACKUP = 900;
- // Process is in the background, but it can't restore its state so we want
- // to try to avoid killing it.
- PROCESS_STATE_HEAVY_WEIGHT = 1000;
+ PROCESS_STATE_BACKUP = 800;
// Process is in the background running a service. Unlike oom_adj, this
// level is used for both the normal running in background state and the
// executing operations state.
- PROCESS_STATE_SERVICE = 1100;
+ PROCESS_STATE_SERVICE = 900;
// Process is in the background running a receiver. Note that from the
// perspective of oom_adj, receivers run at a higher foreground level, but
// for our prioritization here that is not necessary and putting them
// below services means many fewer changes in some process states as they
// receive broadcasts.
- PROCESS_STATE_RECEIVER = 1200;
+ PROCESS_STATE_RECEIVER = 1000;
+ // Same as PROCESS_STATE_TOP but while device is sleeping.
+ PROCESS_STATE_TOP_SLEEPING = 1100;
+ // Process is in the background, but it can't restore its state so we want
+ // to try to avoid killing it.
+ PROCESS_STATE_HEAVY_WEIGHT = 1200;
// Process is in the background but hosts the home activity.
PROCESS_STATE_HOME = 1300;
// Process is in the background but hosts the last shown activity.
@@ -70,9 +70,12 @@
// Process is being cached for later use and is a client of another cached
// process that contains activities.
PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 1600;
+ // Process is being cached for later use and has an activity that corresponds
+ // to an existing recent task.
+ PROCESS_STATE_CACHED_RECENT = 1700;
// Process is being cached for later use and is empty.
- PROCESS_STATE_CACHED_EMPTY = 1700;
+ PROCESS_STATE_CACHED_EMPTY = 1800;
// Process does not exist.
- PROCESS_STATE_NONEXISTENT = 1800;
+ PROCESS_STATE_NONEXISTENT = 1900;
}
diff --git a/core/proto/android/content/clipdata.proto b/core/proto/android/content/clipdata.proto
new file mode 100644
index 0000000..6967b69
--- /dev/null
+++ b/core/proto/android/content/clipdata.proto
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.content;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/content/clipdescription.proto";
+import "frameworks/base/core/proto/android/content/intent.proto";
+
+// An android.content.ClipData object.
+message ClipDataProto {
+ optional android.content.ClipDescriptionProto description = 1;
+
+ // Custom dump of an android.graphics.Bitmap object.
+ message Icon {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+ optional Icon icon = 2;
+
+ // An android.content.ClipData.Item object.
+ message Item {
+ oneof data {
+ string html_text = 1;
+ string text = 2;
+ string uri = 3;
+ android.content.IntentProto intent = 4;
+ bool nothing = 5;
+ }
+ }
+ repeated Item items = 3;
+}
diff --git a/core/proto/android/content/clipdescription.proto b/core/proto/android/content/clipdescription.proto
new file mode 100644
index 0000000..40f4ad3
--- /dev/null
+++ b/core/proto/android/content/clipdescription.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.content;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/persistablebundle.proto";
+
+// An android.content.ClipDescription object.
+message ClipDescriptionProto {
+ repeated string mime_types = 1;
+ optional string label = 2;
+ optional android.os.PersistableBundleProto extras = 3;
+ optional int64 timestamp_ms = 4;
+}
diff --git a/core/proto/android/net/network.proto b/core/proto/android/net/network.proto
new file mode 100644
index 0000000..9c7ea5d
--- /dev/null
+++ b/core/proto/android/net/network.proto
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option java_multiple_files = true;
+
+package android.net;
+
+/**
+ * An android.net.Network object.
+ */
+message NetworkProto {
+ optional int32 net_id = 1;
+}
diff --git a/core/proto/android/net/networkcapabilities.proto b/core/proto/android/net/networkcapabilities.proto
new file mode 100644
index 0000000..e1c2af1
--- /dev/null
+++ b/core/proto/android/net/networkcapabilities.proto
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.net;
+
+option java_multiple_files = true;
+
+/**
+ * An android.net.NetworkCapabilities object.
+ */
+message NetworkCapabilitiesProto {
+ enum Transport {
+ // Indicates this network uses a Cellular transport.
+ TRANSPORT_CELLULAR = 0;
+ // Indicates this network uses a Wi-Fi transport.
+ TRANSPORT_WIFI = 1;
+ // Indicates this network uses a Bluetooth transport.
+ TRANSPORT_BLUETOOTH = 2;
+ // Indicates this network uses an Ethernet transport.
+ TRANSPORT_ETHERNET = 3;
+ // Indicates this network uses a VPN transport.
+ TRANSPORT_VPN = 4;
+ // Indicates this network uses a Wi-Fi Aware transport.
+ TRANSPORT_WIFI_AWARE = 5;
+ // Indicates this network uses a LoWPAN transport.
+ TRANSPORT_LOWPAN = 6;
+ }
+ repeated Transport transports = 1;
+
+ enum NetCapability {
+ // Indicates this is a network that has the ability to reach the
+ // carrier's MMSC for sending and receiving MMS messages.
+ NET_CAPABILITY_MMS = 0;
+ // Indicates this is a network that has the ability to reach the
+ // carrier's SUPL server, used to retrieve GPS information.
+ NET_CAPABILITY_SUPL = 1;
+ // Indicates this is a network that has the ability to reach the
+ // carrier's DUN or tethering gateway.
+ NET_CAPABILITY_DUN = 2;
+ // Indicates this is a network that has the ability to reach the
+ // carrier's FOTA portal, used for over the air updates.
+ NET_CAPABILITY_FOTA = 3;
+ // Indicates this is a network that has the ability to reach the
+ // carrier's IMS servers, used for network registration and signaling.
+ NET_CAPABILITY_IMS = 4;
+ // Indicates this is a network that has the ability to reach the
+ // carrier's CBS servers, used for carrier specific services.
+ NET_CAPABILITY_CBS = 5;
+ // Indicates this is a network that has the ability to reach a Wi-Fi
+ // direct peer.
+ NET_CAPABILITY_WIFI_P2P = 6;
+ // Indicates this is a network that has the ability to reach a carrier's
+ // Initial Attach servers.
+ NET_CAPABILITY_IA = 7;
+ // Indicates this is a network that has the ability to reach a carrier's
+ // RCS servers, used for Rich Communication Services.
+ NET_CAPABILITY_RCS = 8;
+ // Indicates this is a network that has the ability to reach a carrier's
+ // XCAP servers, used for configuration and control.
+ NET_CAPABILITY_XCAP = 9;
+ // Indicates this is a network that has the ability to reach a carrier's
+ // Emergency IMS servers or other services, used for network signaling
+ // during emergency calls.
+ NET_CAPABILITY_EIMS = 10;
+ // Indicates that this network is unmetered.
+ NET_CAPABILITY_NOT_METERED = 11;
+ // Indicates that this network should be able to reach the internet.
+ NET_CAPABILITY_INTERNET = 12;
+ // Indicates that this network is available for general use. If this is
+ // not set applications should not attempt to communicate on this
+ // network. Note that this is simply informative and not enforcement -
+ // enforcement is handled via other means. Set by default.
+ NET_CAPABILITY_NOT_RESTRICTED = 13;
+ // Indicates that the user has indicated implicit trust of this network.
+ // This generally means it's a sim-selected carrier, a plugged in
+ // ethernet, a paired BT device or a wifi the user asked to connect to.
+ // Untrusted networks are probably limited to unknown wifi AP. Set by
+ // default.
+ NET_CAPABILITY_TRUSTED = 14;
+ // Indicates that this network is not a VPN. This capability is set by
+ // default and should be explicitly cleared for VPN networks.
+ NET_CAPABILITY_NOT_VPN = 15;
+ // Indicates that connectivity on this network was successfully
+ // validated. For example, for a network with NET_CAPABILITY_INTERNET,
+ // it means that Internet connectivity was successfully detected.
+ NET_CAPABILITY_VALIDATED = 16;
+ // Indicates that this network was found to have a captive portal in
+ // place last time it was probed.
+ NET_CAPABILITY_CAPTIVE_PORTAL = 17;
+ // Indicates that this network is not roaming.
+ NET_CAPABILITY_NOT_ROAMING = 18;
+ // Indicates that this network is available for use by apps, and not a
+ // network that is being kept up in the background to facilitate fast
+ // network switching.
+ NET_CAPABILITY_FOREGROUND = 19;
+ }
+ repeated NetCapability capabilities = 2;
+
+ // Passive link bandwidth. This is a rough guide of the expected peak
+ // bandwidth for the first hop on the given transport. It is not measured,
+ // but may take into account link parameters (Radio technology, allocated
+ // channels, etc).
+ optional int32 link_up_bandwidth_kbps = 3;
+ optional int32 link_down_bandwidth_kbps = 4;
+
+ optional string network_specifier = 5;
+
+ // True if this object specifies a signal strength.
+ optional bool can_report_signal_strength = 6;
+ // This is a signed integer, and higher values indicate better signal. The
+ // exact units are bearer-dependent. For example, Wi-Fi uses RSSI.
+ // Only valid if can_report_signal_strength is true.
+ optional sint32 signal_strength = 7;
+}
diff --git a/core/proto/android/net/networkrequest.proto b/core/proto/android/net/networkrequest.proto
new file mode 100644
index 0000000..9884464
--- /dev/null
+++ b/core/proto/android/net/networkrequest.proto
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.net;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/net/networkcapabilities.proto";
+
+/**
+ * An android.net.NetworkRequest object.
+ */
+message NetworkRequestProto {
+ enum Type {
+ TYPE_UNKNOWN = 0;
+ // Only used by applications. When an application creates a
+ // NetworkRequest, it does not have a type; the type is set by the
+ // system depending on the method used to file the request
+ // (requestNetwork, registerNetworkCallback, etc.).
+ TYPE_NONE = 1;
+ // The framework will issue callbacks about any and all networks that
+ // match the specified NetworkCapabilities.
+ TYPE_LISTEN = 2;
+ // A hybrid of the two designed such that the framework will issue
+ // callbacks for the single, highest scoring current network (if any)
+ // that matches the capabilities of the default Internet request
+ // (mDefaultRequest), but which cannot cause the framework to either
+ // create or retain the existence of any specific network. Note that
+ // from the point of view of the request matching code, TRACK_DEFAULT is
+ // identical to REQUEST: its special behaviour is not due to different
+ // semantics, but to the fact that the system will only ever create a
+ // TRACK_DEFAULT with capabilities that are identical to the default
+ // request's capabilities, thus causing it to share fate in every way
+ // with the default request.
+ TYPE_TRACK_DEFAULT = 3;
+ // Capable of causing a specific network to be created first (e.g. a
+ // telephony DUN request), the framework will issue callbacks about the
+ // single, highest scoring current network (if any) that matches the
+ // specified NetworkCapabilities.
+ TYPE_REQUEST = 4;
+ // Like REQUEST but does not cause any networks to retain the
+ // NET_CAPABILITY_FOREGROUND capability. A network with no foreground
+ // requests is in the background. A network that has one or more
+ // background requests and loses its last foreground request to a
+ // higher-scoring network will not go into the background immediately,
+ // but will linger and go into the background after the linger timeout.
+ TYPE_BACKGROUND_REQUEST = 5;
+ }
+ // The type of the request. This is only used by the system and is always
+ // NONE elsewhere.
+ optional Type type = 1;
+ // Identifies the request.
+ optional int32 request_id = 2;
+ // Set for legacy requests and the default.
+ optional int32 legacy_type = 3;
+ optional NetworkCapabilitiesProto network_capabilities = 4;
+}
diff --git a/core/proto/android/os/bundle.proto b/core/proto/android/os/bundle.proto
new file mode 100644
index 0000000..6990281
--- /dev/null
+++ b/core/proto/android/os/bundle.proto
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.os;
+
+option java_multiple_files = true;
+
+// An android.os.Bundle object.
+message BundleProto {
+ oneof data {
+ int32 parcelled_data_size = 1;
+ string map_data = 2;
+ }
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index a6db31f..2752a7e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -31,6 +31,7 @@
import "frameworks/base/core/proto/android/server/activitymanagerservice.proto";
import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto";
import "frameworks/base/core/proto/android/server/fingerprint.proto";
+import "frameworks/base/core/proto/android/server/jobscheduler.proto";
import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
import "frameworks/base/core/proto/android/service/appwidget.proto";
@@ -43,6 +44,8 @@
import "frameworks/base/core/proto/android/service/package.proto";
import "frameworks/base/core/proto/android/service/print.proto";
import "frameworks/base/core/proto/android/service/procstats.proto";
+import "frameworks/base/core/proto/android/util/event_log_tags.proto";
+import "frameworks/base/core/proto/android/util/log.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
import "frameworks/base/libs/incident/proto/android/section.proto";
@@ -59,6 +62,8 @@
// the sections are able to be controlled and configured by section ids.
// Instead privacy field options need to be configured in each section proto message.
message IncidentProto {
+ reserved 1001;
+
// Incident header from callers
repeated IncidentHeaderProto header = 1;
// Internal metadata of incidentd
@@ -70,6 +75,52 @@
(section).args = "getprop"
];
+ // Device Logs
+ optional android.util.EventLogTagMapProto event_log_tag_map = 1100 [
+ (section).type = SECTION_FILE,
+ (section).args = "/system/etc/event-log-tags"
+ ];
+
+ optional android.util.LogProto main_logs = 1101 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_MAIN"
+ ];
+
+ optional android.util.LogProto radio_logs = 1102 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_RADIO"
+ ];
+
+ optional android.util.LogProto events_logs = 1103 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_EVENTS"
+ ];
+
+ optional android.util.LogProto system_logs = 1104 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_SYSTEM"
+ ];
+
+ optional android.util.LogProto crash_logs = 1105 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_CRASH"
+ ];
+
+ optional android.util.LogProto stats_logs = 1106 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_STATS"
+ ];
+
+ optional android.util.LogProto security_logs = 1107 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_SECURITY"
+ ];
+
+ optional android.util.LogProto kernel_logs = 1108 [
+ (section).type = SECTION_LOG,
+ (section).args = "LOG_ID_KERNEL"
+ ];
+
// Linux services
optional Procrank procrank = 2000 [
(section).type = SECTION_COMMAND,
@@ -196,4 +247,9 @@
(section).type = SECTION_DUMPSYS,
(section).args = "graphicsstats --proto"
];
+
+ optional com.android.server.job.JobSchedulerServiceDumpProto jobscheduler = 3020 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "jobscheduler --proto"
+ ];
}
diff --git a/core/proto/android/os/persistablebundle.proto b/core/proto/android/os/persistablebundle.proto
new file mode 100644
index 0000000..75ff787
--- /dev/null
+++ b/core/proto/android/os/persistablebundle.proto
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.os;
+
+option java_multiple_files = true;
+
+// An android.os.PersistableBundle object.
+message PersistableBundleProto {
+ oneof data {
+ int32 parcelled_data_size = 1;
+ string map_data = 2;
+ }
+}
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index 59582ec..07b9ad0 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -228,8 +228,9 @@
}
optional PmDexopt pm_dexopt = 20;
+ // Read only properites on the device.
message Ro {
- optional int32 adb_secure = 1;
+ optional bool adb_secure = 1;
optional string arch = 2;
optional bool audio_ignore_effects = 3;
optional bool audio_monitorRotation = 4;
@@ -262,21 +263,29 @@
}
optional Boot boot = 7;
+ // boot.img's properties.
message BootImage {
+ // When the boot.img is built.
optional string build_date = 1;
- optional int32 build_date_utc = 2;
+ // UTC timestamp of build date.
+ optional int64 build_date_utc = 2;
+ // Android Build fingerprint of the build, e.g.
+ // google/marlin/marlin:P/MASTER/android-build/dev-keys
optional string build_fingerprint = 3;
// Next Tag: 4
}
optional BootImage bootimage = 8;
+ // Version of bootloader on device.
optional string bootloader = 9;
+ // Kernel bootmode, e.g. charger.
optional string bootmode = 10;
+ // Android Platform build metadata.
message Build {
optional string date = 1;
- optional int32 date_utc = 2;
+ optional int64 date_utc = 2;
optional string description = 3;
optional string display_id = 4;
optional string host = 5;
@@ -304,7 +313,7 @@
}
optional Build build = 11;
- optional int32 camera_notify_nfc = 12;
+ optional bool camera_notify_nfc = 12;
optional string carrier = 13;
optional bool com_android_dataroaming = 14;
optional bool com_android_prov_mobiledata = 15;
@@ -327,7 +336,7 @@
optional string crypto_state = 21;
optional string crypto_type = 22;
optional string dalvik_vm_native_bridge = 23;
- optional bool debuggable = 24;
+ optional bool debuggable = 24;
optional string frp_pst = 25;
optional string gfx_driver_0 = 26;
@@ -426,7 +435,7 @@
message Vendor {
optional string build_date = 1;
- optional int32 build_date_utc = 2;
+ optional int64 build_date_utc = 2;
optional string build_fingerprint = 3;
}
optional Vendor vendor = 41;
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index fb0ebed..f5d098c 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -582,7 +582,7 @@
optional SettingProto downloads_backup_charging_only = 162;
optional SettingProto automatic_storage_manager_downloads_days_to_retain = 163;
optional SettingProto qs_tiles = 164;
- optional SettingProto demo_user_setup_complete = 165;
+ reserved 165; // Removed demo_user_setup_complete
optional SettingProto instant_apps_enabled = 166;
optional SettingProto device_paired = 167;
optional SettingProto package_verifier_state = 191;
diff --git a/core/proto/android/server/appwindowthumbnail.proto b/core/proto/android/server/appwindowthumbnail.proto
new file mode 100644
index 0000000..e67b854
--- /dev/null
+++ b/core/proto/android/server/appwindowthumbnail.proto
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
+
+package com.android.server.wm.proto;
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link com.android.server.wm.AppWindowThumbnail} object.
+ */
+message AppWindowThumbnailProto {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ optional SurfaceAnimatorProto surface_animator = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
new file mode 100644
index 0000000..f72ca62
--- /dev/null
+++ b/core/proto/android/server/jobscheduler.proto
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.server.job;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/app/jobparameters.proto";
+import "frameworks/base/core/proto/android/content/clipdata.proto";
+import "frameworks/base/core/proto/android/content/component_name.proto";
+import "frameworks/base/core/proto/android/content/intent.proto";
+import "frameworks/base/core/proto/android/net/network.proto";
+import "frameworks/base/core/proto/android/net/networkrequest.proto";
+import "frameworks/base/core/proto/android/os/bundle.proto";
+import "frameworks/base/core/proto/android/os/persistablebundle.proto";
+import "frameworks/base/core/proto/android/server/forceappstandbytracker.proto";
+
+message JobSchedulerServiceDumpProto {
+ optional ConstantsProto settings = 1;
+
+ repeated int32 started_users = 2;
+
+ message RegisteredJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional JobStatusDumpProto dump = 2;
+
+ // A job is ready to be executed if:
+ // is_job_ready && is_user_started && !is_job_pending &&
+ // !is_job_currently_active && !is_uid_backing_up &&
+ // is_component_present.
+ optional bool is_job_ready = 3;
+ optional bool is_user_started = 4;
+ optional bool is_job_pending = 5;
+ optional bool is_job_currently_active = 6;
+ optional bool is_uid_backing_up = 7;
+ optional bool is_component_present = 8;
+ }
+ repeated RegisteredJob registered_jobs = 3;
+
+ repeated StateControllerProto controllers = 4;
+
+ // Which uids are currently in the foreground.
+ message PriorityOverride {
+ optional int32 uid = 1;
+ // Use sint32 instead of an enum since priorities can technically be
+ // negative.
+ optional sint32 override_value = 2;
+ }
+ repeated PriorityOverride priority_overrides = 5;
+
+ // UIDs that are currently performing backups, so their jobs won't be
+ // allowed to run.
+ repeated int32 backing_up_uids = 6;
+
+ optional JobPackageHistoryProto history = 7;
+ optional JobPackageTrackerDumpProto package_tracker = 8;
+
+ message PendingJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional JobStatusDumpProto dump = 2;
+ optional sint32 evaluated_priority = 3;
+ // How long this job has been pending.
+ optional int64 enqueued_duration_ms = 4;
+ }
+ repeated PendingJob pending_jobs = 9;
+
+ // From a service that has currently active or pending jobs.
+ message ActiveJob {
+ message InactiveJob {
+ optional int64 time_since_stopped_ms = 1;
+ // This is not always provided.
+ optional string stopped_reason = 2;
+ }
+ message RunningJob {
+ optional JobStatusShortInfoProto info = 1;
+ // How long this job has been running for.
+ optional int64 running_duration_ms = 2;
+ optional int64 time_until_timeout_ms = 3;
+
+ optional JobStatusDumpProto dump = 4;
+
+ optional sint32 evaluated_priority = 5;
+
+ optional int64 time_since_made_active_ms = 6;
+ // How long this job has been pending.
+ optional int64 pending_duration_ms = 7;
+ }
+ oneof job {
+ InactiveJob inactive = 1;
+ RunningJob running = 2;
+ }
+ }
+ repeated ActiveJob active_jobs = 10;
+
+ // True when JobScheduler is allowed to run third party apps.
+ optional bool is_ready_to_rock = 11;
+ // What was last reported to DeviceIdleController about whether the device
+ // is active.
+ optional bool reported_active = 12;
+ // The current limit on the number of concurrent JobServiceContext entries
+ // we want to keep actively running a job.
+ optional int32 max_active_jobs = 13;
+}
+
+// A com.android.server.job.JobSchedulerService.Constants object.
+message ConstantsProto {
+ // Minimum # of idle jobs that must be ready in order to force the JMS to
+ // schedule things early.
+ optional int32 min_idle_count = 1;
+ // Minimum # of charging jobs that must be ready in order to force the JMS
+ // to schedule things early.
+ optional int32 min_charging_count = 2;
+ // Minimum # of "battery not low" jobs that must be ready in order to force
+ // the JMS to schedule things early.
+ optional int32 min_battery_not_low_count = 3;
+ // Minimum # of "storage not low" jobs that must be ready in order to force
+ // the JMS to schedule things early.
+ optional int32 min_storage_not_low_count = 4;
+ // Minimum # of connectivity jobs that must be ready in order to force the
+ // JMS to schedule things early. 1 == Run connectivity jobs as soon as
+ // ready.
+ optional int32 min_connectivity_count = 5;
+ // Minimum # of content trigger jobs that must be ready in order to force
+ // the JMS to schedule things early.
+ optional int32 min_content_count = 6;
+ // Minimum # of jobs (with no particular constraints) for which the JMS will
+ // be happy running some work early. This (and thus the other min counts)
+ // is now set to 1, to prevent any batching at this level. Since we now do
+ // batching through doze, that is a much better mechanism.
+ optional int32 min_ready_jobs_count = 7;
+ // This is the job execution factor that is considered to be heavy use of
+ // the system.
+ optional double heavy_use_factor = 8;
+ // This is the job execution factor that is considered to be moderate use of
+ // the system.
+ optional double moderate_use_factor = 9;
+ // The number of MAX_JOB_CONTEXTS_COUNT we reserve for the foreground app.
+ optional int32 fg_job_count = 10;
+ // The maximum number of background jobs we allow when the system is in a
+ // normal memory state.
+ optional int32 bg_normal_job_count = 11;
+ // The maximum number of background jobs we allow when the system is in a
+ // moderate memory state.
+ optional int32 bg_moderate_job_count = 12;
+ // The maximum number of background jobs we allow when the system is in a
+ // low memory state.
+ optional int32 bg_low_job_count = 13;
+ // The maximum number of background jobs we allow when the system is in a
+ // critical memory state.
+ optional int32 bg_critical_job_count = 14;
+ // The maximum number of times we allow a job to have itself rescheduled
+ // before giving up on it, for standard jobs.
+ optional int32 max_standard_reschedule_count = 15;
+ // The maximum number of times we allow a job to have itself rescheduled
+ // before giving up on it, for jobs that are executing work.
+ optional int32 max_work_reschedule_count = 16;
+ // The minimum backoff time to allow for linear backoff.
+ optional int64 min_linear_backoff_time_ms = 17;
+ // The minimum backoff time to allow for exponential backoff.
+ optional int64 min_exp_backoff_time_ms = 18;
+ // How often we recalculate runnability based on apps' standby bucket
+ // assignment. This should be prime relative to common time interval lengths
+ // such as a quarter-hour or day, so that the heartbeat drifts relative to
+ // wall-clock milestones.
+ optional int64 standby_heartbeat_time_ms = 19;
+ // Mapping: standby bucket -> number of heartbeats between each sweep of
+ // that bucket's jobs.
+ // Bucket assignments as recorded in the JobStatus objects are normalized to
+ // be indices into this array, rather than the raw constants used by
+ // AppIdleHistory.
+ repeated int32 standby_beats = 20;
+}
+
+message StateControllerProto {
+ message AppIdleController {
+ optional bool is_parole_on = 1;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ optional string source_package_name = 3;
+ // If the constraints are satisfied, then the controller will mark
+ // the job as RUNNABLE, otherwise, it will be WAITING.
+ optional bool are_constraints_satisfied = 4;
+ }
+ repeated TrackedJob tracked_jobs = 2;
+ }
+ message BackgroundJobsController {
+ optional com.android.server.ForceAppStandbyTrackerProto force_app_standby_tracker = 1;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ optional string source_package_name = 3;
+ optional bool is_in_foreground = 4;
+ optional bool is_whitelisted = 5;
+ optional bool can_run_any_in_background = 6;
+ // If the constraints are satisfied, then the controller will mark
+ // the job as RUNNABLE, otherwise, it will be WAITING.
+ optional bool are_constraints_satisfied = 7;
+ }
+ repeated TrackedJob tracked_jobs = 2;
+ }
+ message BatteryController {
+ optional bool is_on_stable_power = 1;
+ optional bool is_battery_not_low = 2;
+
+ // Whether or not the controller is monitoring battery changes.
+ optional bool is_monitoring = 3;
+ // Only valid if is_monitoring is true.
+ optional int32 last_broadcast_sequence_number = 4;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ }
+ repeated TrackedJob tracked_jobs = 5;
+ }
+ message ConnectivityController {
+ optional bool is_connected = 1;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ optional .android.net.NetworkRequestProto required_network = 3;
+ }
+ repeated TrackedJob tracked_jobs = 2;
+ }
+ message ContentObserverController {
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ }
+ repeated TrackedJob tracked_jobs = 1;
+
+ message Observer {
+ optional int32 user_id = 1;
+
+ message TriggerContentData {
+ optional string uri = 1;
+ optional int32 flags = 2;
+
+ // A
+ // com.android.server.job.controllers.ContentObserverController.JobInstance
+ // object.
+ message JobInstance {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+
+ optional int64 trigger_content_update_delay_ms = 3;
+ optional int64 trigger_content_max_delay_ms = 4;
+
+ repeated string changed_authorities = 5;
+ repeated string changed_uris = 6;
+ }
+ repeated JobInstance jobs = 3;
+ }
+ repeated TriggerContentData triggers = 2;
+ }
+ repeated Observer observers = 2;
+ }
+ message DeviceIdleJobsController {
+ // True when in device idle mode.
+ optional bool is_device_idle_mode = 1;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ optional string source_package_name = 3;
+ // If the constraints are satisfied, then the controller will mark
+ // the job as RUNNABLE, otherwise, it will be WAITING.
+ optional bool are_constraints_satisfied = 4;
+ optional bool is_doze_whitelisted = 5;
+ // A job that is exempted from Doze when the app is temp whitelisted
+ // or in the foreground.
+ optional bool is_allowed_in_doze = 6;
+ }
+ repeated TrackedJob tracked_jobs = 2;
+ }
+ message IdleController {
+ optional bool is_idle = 1;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ }
+ repeated TrackedJob tracked_jobs = 2;
+ }
+ message StorageController {
+ optional bool is_storage_not_low = 1;
+ optional int32 last_broadcast_sequence_number = 2;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+ }
+ repeated TrackedJob tracked_jobs = 3;
+ }
+ message TimeController {
+ optional int64 now_elapsed_realtime = 1;
+ optional int64 time_until_next_delay_alarm_ms = 2;
+ optional int64 time_until_next_deadline_alarm_ms = 3;
+
+ message TrackedJob {
+ optional JobStatusShortInfoProto info = 1;
+ optional int32 source_uid = 2;
+
+ optional bool has_timing_delay_constraint = 3;
+ // Only valid if has_timing_delay_constraint is true. Can be
+ // negative if the delay is in the past.
+ optional int64 delay_time_remaining_ms = 4;
+
+ optional bool has_deadline_constraint = 5;
+ // Only valid if has_timing_delay_constraint is true. Can be
+ // negative in certain situations.
+ optional int64 time_remaining_until_deadline_ms = 6;
+ }
+ repeated TrackedJob tracked_jobs = 4;
+ }
+ oneof controller {
+ AppIdleController app_idle = 1;
+ BackgroundJobsController background = 2;
+ BatteryController battery = 3;
+ ConnectivityController connectivity = 4;
+ ContentObserverController content_observer = 5;
+ DeviceIdleJobsController device_idle = 6;
+ IdleController idle = 7;
+ StorageController storage = 8;
+ TimeController time = 9;
+ }
+}
+
+// A com.android.server.job.JobPackageTracker.DataSet object.
+message DataSetProto {
+ optional int64 start_clock_time_ms = 1;
+ // How much time has elapsed since the DataSet was instantiated.
+ optional int64 elapsed_time_ms = 2;
+ optional int64 period_ms = 3;
+
+ // Represents a com.android.server.job.JobPackageTracker.PackageEntry
+ // object, but with some extra data.
+ message PackageEntryProto {
+ optional int32 uid = 1;
+ optional string package_name = 2;
+
+ message State {
+ optional int64 duration_ms = 1;
+ optional int32 count = 2;
+ }
+ optional State pending_state = 3;
+ optional State active_state = 4;
+ optional State active_top_state = 5;
+
+ // True if the PackageEntry is currently pending or has been pending in
+ // the past.
+ optional bool pending = 6;
+ // True if the PackageEntry is currently active or has been active in
+ // the past.
+ optional bool active = 7;
+ // True if the PackageEntry is currently active top or has been active
+ // top in the past.
+ optional bool active_top = 8;
+
+ message StopReasonCount {
+ optional .android.app.JobParametersProto.CancelReason reason = 1;
+ optional int32 count = 2;
+ }
+ repeated StopReasonCount stop_reasons = 9;
+ }
+ repeated PackageEntryProto package_entries = 4;
+
+ optional int32 max_concurrency = 5;
+ optional int32 max_foreground_concurrency = 6;
+}
+
+// Dump from com.android.server.job.GrantedUriPermissions.
+message GrantedUriPermissionsDumpProto {
+ optional int32 flags = 1;
+ optional int32 source_user_id = 2;
+ optional string tag = 3;
+ optional string permission_owner = 4;
+ repeated string uris = 5;
+}
+
+message JobPackageTrackerDumpProto {
+ repeated DataSetProto historical_stats = 1;
+ optional DataSetProto current_stats = 2;
+}
+
+message JobPackageHistoryProto {
+ enum Event {
+ UNKNOWN = 0;
+ START_JOB = 1;
+ STOP_JOB = 2;
+ START_PERIODIC_JOB = 3;
+ STOP_PERIODIC_JOB = 4;
+ }
+ message HistoryEvent {
+ optional Event event = 1;
+ optional int64 time_since_event_ms = 2;
+ optional int32 uid = 3;
+ // Job IDs can technically be negative.
+ optional int32 job_id = 4;
+ optional string tag = 5;
+ // Only valid for STOP_JOB or STOP_PERIODIC_JOB Events.
+ optional .android.app.JobParametersProto.CancelReason stop_reason = 6;
+ }
+ repeated HistoryEvent history_event = 1;
+}
+
+message JobStatusShortInfoProto {
+ optional int32 calling_uid = 1;
+ // Job IDs can technically be negative.
+ optional int32 job_id = 2;
+ optional string battery_name = 3;
+}
+
+// Dump from a com.android.server.job.controllers.JobStatus object.
+message JobStatusDumpProto {
+ // The UID that scheduled the job.
+ optional int32 calling_uid = 1;
+ optional string tag = 2;
+
+ // The UID for which the job is being run.
+ optional int32 source_uid = 3;
+ optional int32 source_user_id = 4;
+ // The package for which the job is being run.
+ optional string source_package_name = 5;
+
+ // Custom dump of android.app.job.JobInfo object.
+ message JobInfo {
+ optional .android.content.ComponentNameProto service = 1;
+
+ optional bool is_periodic = 2;
+ // Only valid if is_periodic is true.
+ optional int64 period_interval_ms = 3;
+ // Only valid if is_periodic is true.
+ optional int64 period_flex_ms = 4;
+
+ optional bool is_persisted = 5;
+ optional sint32 priority = 6;
+ optional int32 flags = 7;
+
+ optional bool requires_charging = 8;
+ optional bool requires_battery_not_low = 9;
+ optional bool requires_device_idle = 10;
+
+ message TriggerContentUri {
+ optional int32 flags = 1;
+ optional string uri = 2;
+ }
+ repeated TriggerContentUri trigger_content_uris = 11;
+ optional int64 trigger_content_update_delay_ms = 12;
+ optional int64 trigger_content_max_delay_ms = 13;
+
+ optional .android.os.PersistableBundleProto extras = 14;
+ optional .android.os.BundleProto transient_extras = 15;
+ optional .android.content.ClipDataProto clip_data = 16;
+
+ optional GrantedUriPermissionsDumpProto granted_uri_permissions = 17;
+
+ optional .android.net.NetworkRequestProto required_network = 18;
+
+ optional int64 total_network_bytes = 19;
+
+ optional int64 min_latency_ms = 20;
+ optional int64 max_execution_delay_ms = 21;
+
+ message Backoff {
+ enum Policy {
+ BACKOFF_POLICY_LINEAR = 0;
+ BACKOFF_POLICY_EXPONENTIAL = 1;
+ }
+ optional Policy policy = 1;
+ optional int64 initial_backoff_ms = 2;
+ }
+ optional Backoff backoff_policy = 22;
+
+ optional bool has_early_constraint = 23;
+ optional bool has_late_constraint = 24;
+ }
+ optional JobInfo job_info = 6;
+
+ enum Constraint {
+ CONSTRAINT_CHARGING = 1;
+ CONSTRAINT_BATTERY_NOT_LOW = 2;
+ CONSTRAINT_STORAGE_NOT_LOW = 3;
+ CONSTRAINT_TIMING_DELAY = 4;
+ CONSTRAINT_DEADLINE = 5;
+ CONSTRAINT_IDLE = 6;
+ CONSTRAINT_CONNECTIVITY = 7;
+ CONSTRAINT_APP_NOT_IDLE = 8;
+ CONSTRAINT_CONTENT_TRIGGER = 9;
+ CONSTRAINT_DEVICE_NOT_DOZING = 10;
+ }
+ repeated Constraint required_constraints = 7;
+ repeated Constraint satisfied_constraints = 8;
+ repeated Constraint unsatisfied_constraints = 9;
+ optional bool is_doze_whitelisted = 10;
+
+ enum TrackingController {
+ TRACKING_BATTERY = 0;
+ TRACKING_CONNECTIVITY = 1;
+ TRACKING_CONTENT = 2;
+ TRACKING_IDLE = 3;
+ TRACKING_STORAGE = 4;
+ TRACKING_TIME = 5;
+ }
+ // Controllers that are currently tracking the job.
+ repeated TrackingController tracking_controllers = 11;
+
+ repeated string changed_authorities = 12;
+ repeated string changed_uris = 13;
+
+ optional .android.net.NetworkProto network = 14;
+
+ // Only the desired data from an android.app.job.JobWorkItem object.
+ message JobWorkItem {
+ optional int32 work_id = 1;
+ optional int32 delivery_count = 2;
+ optional .android.content.IntentProto intent = 3;
+ optional GrantedUriPermissionsDumpProto uri_grants = 4;
+ }
+ repeated JobWorkItem pending_work = 15;
+ repeated JobWorkItem executing_work = 16;
+
+ enum Bucket {
+ ACTIVE = 0;
+ WORKING_SET = 1;
+ FREQUENT = 2;
+ RARE = 3;
+ NEVER = 4;
+ }
+ optional Bucket standby_bucket = 17;
+
+ optional int64 enqueue_duration_ms = 18;
+ // Can be negative if the earliest runtime deadline has passed.
+ optional sint64 time_until_earliest_runtime_ms = 19;
+ // Can be negative if the latest runtime deadline has passed.
+ optional sint64 time_until_latest_runtime_ms = 20;
+
+ optional int32 num_failures = 21;
+
+ optional int64 last_successful_run_time = 22;
+ optional int64 last_failed_run_time = 23;
+}
diff --git a/core/proto/android/server/surfaceanimator.proto b/core/proto/android/server/surfaceanimator.proto
new file mode 100644
index 0000000..60713d7
--- /dev/null
+++ b/core/proto/android/server/surfaceanimator.proto
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
+
+package com.android.server.wm.proto;
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link com.android.server.wm.SurfaceAnimator} object.
+ */
+message SurfaceAnimatorProto {
+ optional string animation_adapter = 1;
+ optional .android.view.SurfaceControlProto leash = 2;
+ optional bool animation_start_delayed = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 12aca78..04bdc5c 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -18,6 +18,8 @@
import "frameworks/base/core/proto/android/content/configuration.proto";
import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/core/proto/android/server/appwindowthumbnail.proto";
+import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
import "frameworks/base/core/proto/android/view/displaycutout.proto";
import "frameworks/base/core/proto/android/view/displayinfo.proto";
import "frameworks/base/core/proto/android/view/windowlayoutparams.proto";
@@ -128,6 +130,12 @@
optional bool fills_parent = 4;
optional .android.graphics.RectProto bounds = 5;
optional bool animation_background_surface_is_dimming = 6;
+ optional bool defer_removal = 7;
+ optional float minimize_amount = 8;
+ optional bool adjusted_for_ime = 9;
+ optional float adjust_ime_amount = 10;
+ optional float adjust_divider_amount = 11;
+ optional .android.graphics.RectProto adjusted_bounds = 12;
}
/* represents Task */
@@ -138,6 +146,7 @@
optional bool fills_parent = 4;
optional .android.graphics.RectProto bounds = 5;
optional .android.graphics.RectProto temp_inset_bounds = 6;
+ optional bool defer_removal = 7;
}
/* represents AppWindowToken */
@@ -145,6 +154,27 @@
/* obtained from ActivityRecord */
optional string name = 1;
optional WindowTokenProto window_token = 2;
+ optional bool last_surface_showing = 3;
+ optional bool is_waiting_for_transition_start = 4;
+ optional bool is_really_animating = 5;
+ optional AppWindowThumbnailProto thumbnail = 6;
+ optional bool fills_parent = 7;
+ optional bool app_stopped = 8;
+ optional bool hidden_requested = 9;
+ optional bool client_hidden = 10;
+ optional bool defer_hiding_client = 11;
+ optional bool reported_drawn = 12;
+ optional bool reported_visible = 13;
+ optional int32 num_interesting_windows = 14;
+ optional int32 num_drawn_windows = 15;
+ optional bool all_drawn = 16;
+ optional bool last_all_drawn = 17;
+ optional bool removed = 18;
+ optional IdentifierProto starting_window = 19;
+ optional bool starting_displayed = 20;
+ optional bool starting_moved = 21;
+ optional bool hidden_set_from_transferred_starting_window = 22;
+ repeated .android.graphics.RectProto frozen_bounds = 23;
}
/* represents WindowToken */
@@ -152,6 +182,9 @@
optional WindowContainerProto window_container = 1;
optional int32 hash_code = 2;
repeated WindowStateProto windows = 3;
+ optional bool hidden = 4;
+ optional bool waiting_to_show = 5;
+ optional bool paused = 6;
}
/* represents WindowState */
@@ -234,6 +267,7 @@
optional ConfigurationContainerProto configuration_container = 1;
optional int32 orientation = 2;
optional bool visible = 3;
+ optional SurfaceAnimatorProto surface_animator = 4;
}
/* represents ConfigurationContainer */
diff --git a/core/proto/android/server/windowmanagertrace.proto b/core/proto/android/server/windowmanagertrace.proto
index 0c65bb2..d96953e 100644
--- a/core/proto/android/server/windowmanagertrace.proto
+++ b/core/proto/android/server/windowmanagertrace.proto
@@ -16,11 +16,7 @@
syntax = "proto2";
-import "frameworks/base/core/proto/android/content/configuration.proto";
-import "frameworks/base/core/proto/android/graphics/rect.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
-import "frameworks/base/core/proto/android/view/displayinfo.proto";
-import "frameworks/base/core/proto/android/view/windowlayoutparams.proto";
package com.android.server.wm.proto;
diff --git a/core/proto/android/util/event_log_tags.proto b/core/proto/android/util/event_log_tags.proto
new file mode 100644
index 0000000..cb039be
--- /dev/null
+++ b/core/proto/android/util/event_log_tags.proto
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.util;
+
+option java_multiple_files = true;
+
+// Proto representation of event.logtags.
+// Usually sit in /system/etc/event-log-tags.
+message EventLogTagMapProto {
+ repeated EventLogTag event_log_tags = 1;
+}
+
+message EventLogTag {
+ optional uint32 tag_number = 1; // keyed by tag number.
+ optional string tag_name = 2;
+
+ message ValueDescriptor {
+ optional string name = 1;
+
+ enum DataType {
+ UNKNOWN = 0;
+ INT = 1;
+ LONG = 2;
+ STRING = 3;
+ LIST = 4;
+ FLOAT = 5;
+ }
+ optional DataType type = 2;
+
+ enum DataUnit {
+ UNSET = 0; // this field is optional, so default is unset
+ OBJECTS = 1; // Number of objects
+ BYTES = 2; // Number of bytes (default for type of int/long)
+ MILLISECONDS = 3; // Number of milliseconds
+ ALLOCATIONS = 4; // Number of allocations
+ ID = 5; // Id
+ PERCENT = 6; // Percent
+ SECONDS = 115; // 's', Number of seconds (monotonic time)
+ }
+ optional DataUnit unit = 3;
+ }
+ repeated ValueDescriptor value_descriptors = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/util/log.proto b/core/proto/android/util/log.proto
new file mode 100644
index 0000000..fd4fa9e
--- /dev/null
+++ b/core/proto/android/util/log.proto
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.util;
+
+option java_multiple_files = true;
+
+// Represents a Text Log in logd
+// Next Tag: 9
+message TextLogEntry {
+ optional uint64 sec = 1;
+ optional uint64 nanosec = 2;
+
+ enum LogPriority {
+ LOG_UNKNOWN = 0;
+ LOG_DEFAULT = 1;
+ LOG_VERBOSE = 2;
+ LOG_DEBUG = 3;
+ LOG_INFO = 4;
+ LOG_WARN = 5;
+ LOG_ERROR = 6;
+ LOG_FATAL = 7;
+ LOG_SILENT = 8;
+ }
+ optional LogPriority priority = 3;
+ optional int32 uid = 4;
+ optional int32 pid = 5;
+ optional int32 tid = 6;
+ optional string tag = 7;
+ optional string log = 8;
+}
+
+// Represents a Binary Log in logd, need to look event-log-tags for more info.
+// Next Tag: 8
+message BinaryLogEntry {
+ optional uint64 sec = 1;
+ optional uint64 nanosec = 2;
+ optional int32 uid = 3;
+ optional int32 pid = 4;
+ optional int32 tid = 5;
+
+ // Index of the event tag, can look up in event-log-tags file
+ optional uint32 tag_index = 6;
+
+ message Elem {
+ // must be sync with AOSP liblog's log.h
+ enum Type {
+ EVENT_TYPE_LIST_STOP = 10; // ascii decimal value of char '\n'
+ EVENT_TYPE_UNKNOWN = 63; // ascii decimal value of char '?'
+
+ EVENT_TYPE_INT = 0;
+ EVENT_TYPE_LONG = 1;
+ EVENT_TYPE_STRING = 2;
+ EVENT_TYPE_LIST = 3;
+ EVENT_TYPE_FLOAT = 4;
+ }
+ optional Type type = 1 [default=EVENT_TYPE_UNKNOWN];
+
+ oneof value {
+ int32 val_int32 = 2;
+ int64 val_int64 = 3;
+ string val_string = 4;
+ float val_float = 5;
+ }
+ }
+ repeated Elem elems = 7;
+}
+
+message LogProto {
+ repeated TextLogEntry text_logs = 1;
+
+ repeated BinaryLogEntry binary_logs = 2;
+}
+
diff --git a/core/proto/android/view/surfacecontrol.proto b/core/proto/android/view/surfacecontrol.proto
new file mode 100644
index 0000000..9288b4f
--- /dev/null
+++ b/core/proto/android/view/surfacecontrol.proto
@@ -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.
+ */
+
+syntax = "proto2";
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.SurfaceControl} object.
+ */
+message SurfaceControlProto {
+ optional int32 hash_code = 1;
+ optional string name = 2;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 52bfcde..4bf1cb0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -159,6 +159,8 @@
<protected-broadcast
android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
@@ -173,6 +175,8 @@
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
@@ -566,6 +570,11 @@
<!-- Made protected in P (was introduced in JB-MR2) -->
<protected-broadcast android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
+ <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
+
+ <!-- Added in P -->
+ <protected-broadcast android:name="android.app.action.PROFILE_OWNER_CHANGED" />
+ <protected-broadcast android:name="android.app.action.TRANSFER_OWNERSHIP_COMPLETE" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -1797,6 +1806,15 @@
<permission android:name="android.permission.ALLOCATE_AGGRESSIVE"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi @hide
+ Allows an application to use reserved disk space.
+ <p>Not for use by third-party applications. Should only be requested by
+ apps that provide core system functionality, to ensure system stability
+ when disk is otherwise completely full.
+ -->
+ <permission android:name="android.permission.USE_RESERVED_DISK"
+ android:protectionLevel="signature|privileged" />
+
<!-- ================================== -->
<!-- Permissions for screenlock -->
<!-- ================================== -->
@@ -2835,6 +2853,16 @@
android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
android:protectionLevel="signature" />
+ <!-- @hide
+ Allows an application to change the status of Scoped Access Directory requests granted or
+ rejected by the user.
+ <p>This permission should <em>only</em> be requested by the platform
+ settings app. This permission cannot be granted to third-party apps.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to delete cache files.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DELETE_CACHE_FILES"
@@ -3125,6 +3153,12 @@
<permission android:name="android.permission.BACKUP"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows application to manage RecoverableKeyStoreLoader.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RECOVER_KEYSTORE"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows a package to launch the secure full-backup confirmation UI.
ONLY the system process may hold this permission.
@hide -->
@@ -3918,6 +3952,14 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.server.updates.CarrierIdInstallReceiver"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="com.android.internal.intent.action.UPDATE_CARRIER_ID_DB" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
<receiver android:name="com.android.server.MasterClearReceiver"
android:permission="android.permission.MASTER_CLEAR">
<intent-filter
diff --git a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
new file mode 100644
index 0000000..3254ebb
--- /dev/null
+++ b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<!-- This should be kept in sync with task_open_enter.xml -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" android:zAdjustment="top">
+
+ <alpha android:fromAlpha="0" android:toAlpha="1.0"
+ android:startOffset="300"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quart"
+ android:duration="167"/>
+
+ <translate android:fromYDelta="110%" android:toYDelta="0"
+ android:startOffset="300"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:duration="417"/>
+
+ <!-- To keep the thumbnail around longer -->
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:startOffset="717"
+ android:duration="200"/>
+</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 e511cc9..b73e14f 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
-
+<!-- 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">
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
new file mode 100644
index 0000000..ad89fde
--- /dev/null
+++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<!-- 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">
+
+ <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"/>
+
+ <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"/>
+
+ <!-- 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"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable/messaging_message_background.xml b/core/res/res/drawable/messaging_message_background.xml
deleted file mode 100644
index 8a2096a..0000000
--- a/core/res/res/drawable/messaging_message_background.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- android:tint="#14000000">
- <corners android:radius="4dp" />
- <padding android:bottom="6dp"
- android:left="8dp"
- android:right="8dp"
- android:top="6dp" />
-</shape>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 3a28f4d..20bdf3f 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -41,6 +41,24 @@
android:singleLine="true"
/>
<TextView
+ android:id="@+id/header_text_secondary_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/header_text_secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:visibility="gone"
+ android:singleLine="true"/>
+ <TextView
android:id="@+id/header_text_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index f72230b..a72ad53 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -21,10 +21,7 @@
android:layout_height="wrap_content"
android:tag="messaging"
>
- <include layout="@layout/notification_template_header"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/notification_header_height"
- android:layout_marginEnd="56dp"/>
+ <include layout="@layout/notification_template_header"/>
<LinearLayout
android:id="@+id/notification_action_list_margin_target"
android:layout_width="match_parent"
@@ -39,28 +36,19 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="@dimen/notification_content_margin_end"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:minHeight="@dimen/notification_min_content_height"
android:layout_marginBottom="@dimen/notification_content_margin_bottom"
android:orientation="vertical"
>
- <include layout="@layout/notification_template_part_line1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/notification_messaging"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
android:spacing="@dimen/notification_messaging_spacing" />
</LinearLayout>
</LinearLayout>
<include layout="@layout/notification_material_action_list" />
- <include layout="@layout/notification_template_right_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="18dp"
- android:layout_gravity="top|end"/>
+ <include layout="@layout/notification_template_right_icon"/>
</com.android.internal.widget.MessagingLayout>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 8973ceb..4ac308a 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -24,7 +24,7 @@
android:id="@+id/message_icon"
android:layout_width="@dimen/messaging_avatar_size"
android:layout_height="@dimen/messaging_avatar_size"
- android:layout_marginEnd="8dp"
+ android:layout_marginEnd="12dp"
android:scaleType="centerCrop"
android:importantForAccessibility="no" />
<com.android.internal.widget.RemeasuringLinearLayout
@@ -32,19 +32,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
+ <com.android.internal.widget.ImageFloatingTextView
+ android:id="@+id/message_name"
+ style="@style/Widget.Material.Notification.MessagingName"
+ android:layout_width="wrap_content"
+ />
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/group_message_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:spacing="2dp"
android:layout_weight="1"/>
- <com.android.internal.widget.ImageFloatingTextView
- android:id="@+id/message_name"
- style="@style/Widget.Material.Notification.MessagingName"
- android:layout_width="wrap_content"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="2dp"
- />
</com.android.internal.widget.RemeasuringLinearLayout>
</com.android.internal.widget.MessagingGroup>
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 8fb2887..0b97e45 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -19,7 +19,7 @@
android:id="@+id/right_icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="36dp"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
android:layout_gravity="top|end">
<ImageView android:id="@+id/right_icon"
android:layout_width="@dimen/notification_right_icon_size"
@@ -32,8 +32,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="top|end"
- android:layout_marginTop="28dp"
- android:layout_marginEnd="12dp"
+ android:layout_marginTop="27dp"
+ android:layout_marginEnd="16dp"
android:background="@drawable/notification_reply_background"
android:src="@drawable/ic_reply_notification"
android:scaleType="center"
diff --git a/core/res/res/values-af/required_apps_managed_device.xml b/core/res/res/values-af/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-af/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-af/required_apps_managed_profile.xml b/core/res/res/values-af/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-af/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-af/required_apps_managed_user.xml b/core/res/res/values-af/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-af/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 1646073..1bb3417 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Titelloos>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tik om alle netwerke te sien"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Koppel"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netwerke"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi sal outomaties aanskakel"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wanneer jy naby \'n gestoorde hoëgehaltenetwerk is"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Moenie weer aanskakel nie"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Meld aan by Wi-Fi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Meld by netwerk aan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kon nie die kortpad teruglaai nie omdat die program nie rugsteun en teruglaai steun nie"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kon nie teruglaai nie omdat programondertekening nie ooreenstem nie"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kon nie kortpad teruglaai nie"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/required_apps_managed_device.xml b/core/res/res/values-am/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-am/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-am/required_apps_managed_profile.xml b/core/res/res/values-am/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-am/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-am/required_apps_managed_user.xml b/core/res/res/values-am/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-am/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 868b065..0a996ca 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"ኪባ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ርዕስ አልባ>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ሁሉንም አውታረ መረቦችን ለማየት መታ ያድርጉ"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"አገናኝ"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ሁሉም አውታረ መረቦች"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi በራስ-ሰር ይበራል"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ከፍተኛ ጥራት ያለው የተቀመጠ አውታረ መረብ አቅራቢያ ሲሆኑ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"መልሰህ አታብራ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ወደ አውታረ መረብ በመለያ ይግቡ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"መተግበሪያ ምትኬን እና ወደ ነበረበት መመለስን ሳለማይደግፍ አቋራጭ ወደ ነበረበት ሊመለስ አልቻለም"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"በመተግበሪያ ፊርማ አለመዛመድ አቋራጭን ወደነበረበት መመለስ አልተቻለም"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"አቋራጭን ወደ ነበረበት መመለስ አልተቻለም"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/required_apps_managed_device.xml b/core/res/res/values-ar/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ar/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ar/required_apps_managed_profile.xml b/core/res/res/values-ar/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ar/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ar/required_apps_managed_user.xml b/core/res/res/values-ar/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ar/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2f69bd5..e929bf8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"بايت"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"كيلوبايت"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"ميغابايت"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"غيغابايت"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
<string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<بلا عنوان>"</string>
@@ -47,7 +51,7 @@
<string name="needPuk2" msgid="4526033371987193070">"اكتب PUK2 لإلغاء تأمين شريحة SIM."</string>
<string name="enablePin" msgid="209412020907207950">"محاولة غير ناجحة، مكّن قفل SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
- <item quantity="zero">لم يتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدها قفل شريحة SIM.</item>
+ <item quantity="zero">لم يتبق لديك أي محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدها قفل شريحة SIM.</item>
<item quantity="two">يتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدهما قفل شريحة SIM.</item>
<item quantity="few">يتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات يتم بعدها قفل شريحة SIM.</item>
<item quantity="many">يتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة يتم بعدها قفل شريحة SIM.</item>
@@ -444,9 +448,9 @@
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"يتيح للتطبيق تغيير المنطقة الزمنية للتلفزيون."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"للسماح للتطبيق بتغيير المنطقة الزمنية للهاتف."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"البحث عن حسابات على الجهاز"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"للسماح للتطبيق بالحصول على قائمة بالحسابات التي يعرفها الجهاز اللوحي. وقد يتضمن ذلك أية حسابات تم إنشاؤها بواسطة التطبيقات التي ثبتها."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"يتيح للتطبيق الحصول على قائمة بالحسابات المعروفة في التلفزيون. وقد يتضمن هذا أية حسابات أنشأتها التطبيقات التي ثبتها."</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"للسماح للتطبيق بالحصول على قائمة بالحسابات التي يعرفها الهاتف. وقد يتضمن ذلك أية حسابات تم إنشاؤها بواسطة التطبيقات التي ثبتها."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"للسماح للتطبيق بالحصول على قائمة بالحسابات التي يعرفها الجهاز اللوحي. وقد يتضمن ذلك أي حسابات تم إنشاؤها بواسطة التطبيقات التي ثبتها."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"يتيح للتطبيق الحصول على قائمة بالحسابات المعروفة في التلفزيون. وقد يتضمن هذا أي حسابات أنشأتها التطبيقات التي ثبتها."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"للسماح للتطبيق بالحصول على قائمة بالحسابات التي يعرفها الهاتف. وقد يتضمن ذلك أي حسابات تم إنشاؤها بواسطة التطبيقات التي ثبتها."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"عرض اتصالات الشبكة"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"للسماح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"حق الوصول الكامل إلى الشبكة"</string>
@@ -468,7 +472,7 @@
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"يتيح للتطبيق تهيئة تلفزيون بلوتوث المحلي، واكتشاف الأجهزة البعيدة وإقرانها."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"الاتصال بـشبكة WiMAX وقطع الاتصال بها"</string>
- <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"للسماح للتطبيق بتحديد ما إذا تم تمكين WiMAX وتحديد معلومات حول أية شبكات WiMAX متصلة."</string>
+ <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"للسماح للتطبيق بتحديد ما إذا تم تمكين WiMAX وتحديد معلومات حول أي شبكات WiMAX متصلة."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"تغيير حالة WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"للسماح للتطبيق بتوصيل الجهاز اللوحي بشبكات WiMAX وقطع اتصاله بها."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"يتيح للتطبيق توصيل التلفزيون أو إلغاء توصيله بشبكات WiMAX."</string>
@@ -813,7 +817,7 @@
<string name="granularity_label_line" msgid="5764267235026120888">"سطر"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"تعذّر اختبار المصنع"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"إجراء FACTORY_TEST غير متاح سوى للحزم المثبتة في /system/app."</string>
- <string name="factorytest_no_action" msgid="872991874799998561">"لم يتم العثور على أية حزمة توفر إجراء FACTORY_TEST."</string>
+ <string name="factorytest_no_action" msgid="872991874799998561">"لم يتم العثور على أي حزمة توفر إجراء FACTORY_TEST."</string>
<string name="factorytest_reboot" msgid="6320168203050791643">"إعادة تشغيل"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"تعرض الصفحة في \"<xliff:g id="TITLE">%s</xliff:g>\":"</string>
<string name="js_dialog_title_default" msgid="6961903213729667573">"جافا سكريبت"</string>
@@ -1182,7 +1186,7 @@
<string name="ringtone_picker_title_notification" msgid="4837740874822788802">"أصوات الإشعار"</string>
<string name="ringtone_unknown" msgid="3914515995813061520">"غير معروف"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
- <item quantity="zero">لا تتوفر أية شبكات Wi-Fi</item>
+ <item quantity="zero">لا تتوفر أي شبكات Wi-Fi</item>
<item quantity="two">تتوفر شبكتا Wi-Fi</item>
<item quantity="few">تتوفر شبكات Wi-Fi</item>
<item quantity="many">تتوفر شبكات Wi-Fi</item>
@@ -1190,7 +1194,7 @@
<item quantity="one">تتوفر شبكة Wi-Fi واحدة</item>
</plurals>
<plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
- <item quantity="zero">لا تتوفر أية شبكات Wi-Fi مفتوحة</item>
+ <item quantity="zero">لا تتوفر أي شبكات Wi-Fi مفتوحة</item>
<item quantity="two">تتوفر شبكتا Wi-Fi مفتوحتان</item>
<item quantity="few">تتوفر شبكات Wi-Fi مفتوحة</item>
<item quantity="many">تتوفر شبكات Wi-Fi مفتوحة</item>
@@ -1204,6 +1208,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"انقر للاطلاع على جميع الشبكات"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"اتصال"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"جميع الشبكات"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"سيتم تشغيل شبكة Wi-Fi تلقائيًا."</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"عندما تكون بالقرب من شبكة محفوظة عالية الجودة"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"عدم إعادة التشغيل"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"تسجيل الدخول إلى الشبكة"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1406,7 +1413,7 @@
<string name="back_button_label" msgid="2300470004503343439">"رجوع"</string>
<string name="next_button_label" msgid="1080555104677992408">"التالي"</string>
<string name="skip_button_label" msgid="1275362299471631819">"تخطي"</string>
- <string name="no_matches" msgid="8129421908915840737">"ليس هناك أية مطابقات"</string>
+ <string name="no_matches" msgid="8129421908915840737">"ليس هناك أي مطابقات"</string>
<string name="find_on_page" msgid="1946799233822820384">"بحث في الصفحة"</string>
<plurals name="matches_found" formatted="false" msgid="1210884353962081884">
<item quantity="zero"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
@@ -1940,4 +1947,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"تعذّرت استعادة الاختصار لأن التطبيق لا يوفِّر إمكانية النسخ الاحتياطي والاستعادة"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"تعذّرت استعادة الاختصار بسبب عدم تطابق توقيع التطبيق"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"تعذّرت استعادة الاختصار"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/required_apps_managed_device.xml b/core/res/res/values-az/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-az/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-az/required_apps_managed_profile.xml b/core/res/res/values-az/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-az/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-az/required_apps_managed_user.xml b/core/res/res/values-az/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-az/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index a90ef03..8069d6c 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"Başlıqsız"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Bütün şəbəkələri görmək üçün klikləyin"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Qoşulun"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Bütün Şəbəkələr"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi avtomatik olaraq aktiv ediləcək"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Yadda saxlanmış yüksək keyfiyyətli şəbəkələr yaxınlıqda olduqda"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Yenidən aktiv etməyin"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi şəbəkəsinə daxil ol"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Şəbəkəyə daxil olun"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Qısayolu bərpa etmək mümkün olmadı, çünki tətbiq yedəkləməni və bərpa etməyi dəstəkləmir"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tətbiqin imza uyğunsuzluğu səbəbilə qısayolu bərpa etmək mümkün olmadı"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Qısayolu bərpa etmək mümkün olmadı"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/required_apps_managed_device.xml b/core/res/res/values-b+sr+Latn/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-b+sr+Latn/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-b+sr+Latn/required_apps_managed_profile.xml b/core/res/res/values-b+sr+Latn/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-b+sr+Latn/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-b+sr+Latn/required_apps_managed_user.xml b/core/res/res/values-b+sr+Latn/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-b+sr+Latn/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 6725865..bb5a404 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez naslova>"</string>
@@ -1138,6 +1142,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite da biste videli sve mreže"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Poveži"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi će se automatski uključiti"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne uključuj ponovo"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijavite se na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1835,4 +1842,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Vraćanje prečice nije uspelo jer aplikacija ne podržava pravljenje rezervne kopije i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Vraćanje prečice nije uspelo jer se potpisi aplikacija ne podudaraju"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Vraćanje prečice nije uspelo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/required_apps_managed_device.xml b/core/res/res/values-be/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-be/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-be/required_apps_managed_profile.xml b/core/res/res/values-be/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-be/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-be/required_apps_managed_user.xml b/core/res/res/values-be/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-be/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index ca75fac..b5e28b3 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Мб"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без назвы>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Дакраніцеся, каб убачыць усе сеткі"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Падключыцца"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Усе сеткі"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi уключыцца аўтаматычна"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Побач з захаванай сеткай з высакаякасным сігналам"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не ўключаць зноў"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Уваход у сетку Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Увайдзіце ў сетку"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Не атрымалася аднавіць ярлык, бо праграма не падтрымлівае рэзервовае капіраванне і аднаўленне"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Не атрымалася аднавіць ярлык з-за несупадзення подпісаў праграм"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Не атрымалася аднавіць ярлык"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/required_apps_managed_device.xml b/core/res/res/values-bg/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-bg/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bg/required_apps_managed_profile.xml b/core/res/res/values-bg/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-bg/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bg/required_apps_managed_user.xml b/core/res/res/values-bg/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-bg/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 44f183f..e069c4e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без заглавие>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Докоснете, за да видите всички мрежи"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Свързване"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Всички мрежи"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ще се включи автоматично"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Когато сте в района на запазена мрежа с високо качество"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Без повторно включване"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Влизане в Wi-Fi мрежа"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Вход в мрежата"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Прекият път не можа да бъде възстановен, защото приложението не поддържа създаването на резервно копие и възстановяването"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Прекият път не можа да бъде възстановен поради несъответствие в подписа на приложението"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Прекият път не можа да бъде възстановен"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/required_apps_managed_device.xml b/core/res/res/values-bn/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-bn/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bn/required_apps_managed_profile.xml b/core/res/res/values-bn/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-bn/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bn/required_apps_managed_user.xml b/core/res/res/values-bn/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-bn/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index fa3c9b1d..9b1f6c3 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"বাইট"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<শিরোনামহীন>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"সমস্ত নেটওয়ার্ক দেখতে ট্যাপ করুন"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"সংযুক্ত করুন"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"সমস্ত নেটওয়ার্ক"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ওয়াই-ফাই নিজে থেকেই চালু হবে"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"যখন আপনি একটি উচ্চ মানের সংরক্ষিত নেটওয়ার্ক কাছাকাছি থাকেন"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"আবার চালু করবেন না"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"নেটওয়ার্কে সাইন-ইন করুন"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"শর্টকাট ফিরিয়ে আনা যায়নি কারণ অ্যাপটিতে \'ব্যাক-আপ এবং রিস্টোর\' করার সুবিধা নেই"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"শর্টকাট ফিরিয়ে আনা যায়নি কারণ অ্যাপের সিগ্নেচারটি মিল হচ্ছে না"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"শর্টকাট ফিরিয়ে আনা যায়নি"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/required_apps_managed_device.xml b/core/res/res/values-bs/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-bs/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bs/required_apps_managed_profile.xml b/core/res/res/values-bs/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-bs/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bs/required_apps_managed_user.xml b/core/res/res/values-bs/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-bs/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c93a0e9..c79566b 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez naslova>"</string>
@@ -86,7 +90,7 @@
<string name="notification_channel_network_alert" msgid="4427736684338074967">"Upozorenja"</string>
<string name="notification_channel_call_forward" msgid="2419697808481833249">"Preusmjeravanje poziva"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Način rada za hitni povratni poziv"</string>
- <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Status mobilnih podataka"</string>
+ <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Status prijenosa podataka na mobilnoj mreži"</string>
<string name="notification_channel_sms" msgid="3441746047346135073">"SMS poruke"</string>
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"Poruke govorne pošte"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi pozivanje"</string>
@@ -1140,6 +1144,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite da vidite sve mreže"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Povežite se"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi veza će se automatski uključiti"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nemoj ponovo uključiti"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1150,7 +1157,7 @@
<string name="network_switch_metered_detail" msgid="775163331794506615">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, uređaj koristi mrežu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata usluge."</string>
<string name="network_switch_metered_toast" msgid="5779283181685974304">"Prebačeno iz mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> u <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mrežu"</string>
<string-array name="network_switch_type_name">
- <item msgid="3979506840912951943">"mobilni podaci"</item>
+ <item msgid="3979506840912951943">"prijenos podataka na mobilnoj mreži"</item>
<item msgid="75483255295529161">"Wi-Fi"</item>
<item msgid="6862614801537202646">"Bluetooth"</item>
<item msgid="5447331121797802871">"Ethernet"</item>
@@ -1837,4 +1844,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Prečica nije uspješno vraćena jer aplikacija ne podržava izradu sigurnosne kopije i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Prečica nije uspješno vraćena zbog nepodudaranja potpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Prečica nije uspješno vraćena"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/required_apps_managed_device.xml b/core/res/res/values-ca/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ca/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ca/required_apps_managed_profile.xml b/core/res/res/values-ca/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ca/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ca/required_apps_managed_user.xml b/core/res/res/values-ca/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ca/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 64d0ccd..ea09008 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sense títol>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca per veure totes les xarxes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connecta"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Totes les xarxes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"La Wi-Fi s\'activarà automàticament"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quan siguis a prop d\'una xarxa de qualitat desada"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No tornis a activar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia la sessió a la xarxa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia la sessió a la xarxa"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"No s\'ha pogut restaurar la drecera perquè l\'aplicació no permet la còpia de seguretat ni la restauració"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"No s\'ha pogut restaurar la drecera perquè la signatura de l\'aplicació no coincideix"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"No s\'ha pogut restaurar la drecera"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/required_apps_managed_device.xml b/core/res/res/values-cs/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-cs/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-cs/required_apps_managed_profile.xml b/core/res/res/values-cs/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-cs/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-cs/required_apps_managed_user.xml b/core/res/res/values-cs/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-cs/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0f24965..684c257 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez názvu>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Klepnutím zobrazíte všechny sítě"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Připojit"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Všechny sítě"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi se zapne automaticky"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Když budete v dosahu kvalitní uložené sítě"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Znovu nezapínat"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Přihlásit se k síti Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Přihlásit se k síti"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Zkratku nelze obnovit, protože aplikace nepodporuje zálohování a obnovu"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Zkratku nelze obnovit, protože se neshoduje podpis aplikace"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Zkratku nelze obnovit"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/required_apps_managed_device.xml b/core/res/res/values-da/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-da/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-da/required_apps_managed_profile.xml b/core/res/res/values-da/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-da/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-da/required_apps_managed_user.xml b/core/res/res/values-da/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-da/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0581742..90b7e5e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"b"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Mb"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"Tb"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Pb"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Uden titel>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tryk for at se alle netværk"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Opret forbindelse"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netværk"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi aktiveres automatisk"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Når du er i nærheden af et gemt netværk af høj kvalitet"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Aktivér ikke igen"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log ind på Wi-Fi-netværk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log ind på netværk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1463,7 +1470,7 @@
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM-kort"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobiloperatøren for at få flere oplysninger."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobilselskabet for at få flere oplysninger."</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Indtast den ønskede pinkode"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Bekræft den ønskede pinkode"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM-kortet låses op…"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Genvejen kunne ikke gendannes, da appen ikke understøtter backup og gendannelse"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Genvejen kunne ikke gendannes på grund af uoverensstemmelse i appsignatur"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Genvejen kunne ikke gendannes"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/required_apps_managed_device.xml b/core/res/res/values-de/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-de/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-de/required_apps_managed_profile.xml b/core/res/res/values-de/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-de/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-de/required_apps_managed_user.xml b/core/res/res/values-de/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-de/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f694064..9d317eb 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Unbenannt>"</string>
@@ -545,8 +549,8 @@
<string name="permdesc_handoverStatus" msgid="4788144087245714948">"Ermöglicht dieser App, Informationen zu aktuellen Android Beam-Übertragungen zu erhalten"</string>
<string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM-Zertifikate entfernen"</string>
<string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ermöglicht einer App das Entfernen von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden."</string>
- <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"An einen Mobilfunkanbieter-SMS/MMS-Dienst binden"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Inhaber die Bindung an die Oberfläche eines Mobilfunkanbieter-SMS/MMS-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"An einen Mobilfunkanbieter-Messaging-Dienst binden"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Inhaber die Bindung an die Oberfläche eines Mobilfunkanbieter-Messaging-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
<string name="permlab_bindCarrierServices" msgid="3233108656245526783">"An Mobilfunkanbieter-Dienste binden"</string>
<string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Ermöglicht dem Inhaber die Bindung an Mobilfunkanbieter-Dienste. Für normale Apps sollte dies nicht erforderlich sein."</string>
<string name="permlab_access_notification_policy" msgid="4247510821662059671">"Auf \"Nicht stören\" zugreifen"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tippen, um alle Netzwerke zu sehen"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Verbinden"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle Netzwerke"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WLAN wird automatisch aktiviert"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wenn du in der Nähe eines sicheren gespeicherten Netzwerks bist"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nicht wieder aktivieren"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN anmelden"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Im Netzwerk anmelden"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1640,7 +1647,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Von deinem Administrator installiert"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Von deinem Administrator aktualisiert"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Von deinem Administrator gelöscht"</string>
- <string name="battery_saver_description" msgid="5394663545060026162">"Der Energiesparmodus schont den Akku, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion, Standortdienste sowie die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail, SMS/MMS und andere Apps, die auf deinem Gerät synchronisiert werden, werden möglicherweise nur aktualisiert, wenn du sie öffnest.\n\nDer Energiesparmodus wird automatisch deaktiviert, wenn dein Gerät aufgeladen wird."</string>
+ <string name="battery_saver_description" msgid="5394663545060026162">"Der Energiesparmodus schont den Akku, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion, Standortdienste sowie die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail, Messaging und andere Apps, die auf deinem Gerät synchronisiert werden, werden möglicherweise nur aktualisiert, wenn du sie öffnest.\n\nDer Energiesparmodus wird automatisch deaktiviert, wenn dein Gerät aufgeladen wird."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Mit dem Datensparmodus wird die Datennutzung verringert, indem verhindert wird, dass im Hintergrund Daten von Apps gesendet oder empfangen werden. Datenzugriffe sind mit einer aktiven App zwar möglich, erfolgen aber seltener. Als Folge davon könnten Bilder beispielsweise erst dann sichtbar werden, wenn sie angetippt werden."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Datensparmodus aktivieren?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Aktivieren"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Verknüpfung konnte nicht wiederhergestellt werden, weil die App keine Sicherung und keine Wiederherstellung unterstützt"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Verknüpfung konnte nicht wiederhergestellt werden, weil die App-Signatur nicht übereinstimmt"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Verknüpfung konnte nicht wiederhergestellt werden"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/required_apps_managed_device.xml b/core/res/res/values-el/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-el/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-el/required_apps_managed_profile.xml b/core/res/res/values-el/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-el/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-el/required_apps_managed_user.xml b/core/res/res/values-el/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-el/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index c20a03f..9aa3eb5 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Χωρίς τίτλο>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Πατήστε για να δείτε όλα τα δίκτυα"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Σύνδεση"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Όλα τα δίκτυα"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Το Wi‑Fi θα ενεργοποιηθεί αυτόματα"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Όταν βρίσκεστε κοντά σε αποθηκευμένο δίκτυο υψηλής ποιότητας"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Να μην ενεργοποιηθεί ξανά"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Συνδεθείτε στο δίκτυο Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Σύνδεση στο δίκτυο"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Δεν ήταν δυνατή η επαναφορά της συντόμευσης, επειδή η εφαρμογή δεν υποστηρίζει τη δημιουργία αντιγράφων ασφαλείας και την επαναφορά"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Δεν ήταν δυνατή η επαναφορά της συντόμευσης, λόγω αναντιστοιχίας της υπογραφής εφαρμογής"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Δεν ήταν δυνατή η επαναφορά της συντόμευσης"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/required_apps_managed_device.xml b/core/res/res/values-en-rAU/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-en-rAU/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rAU/required_apps_managed_profile.xml b/core/res/res/values-en-rAU/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-en-rAU/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rAU/required_apps_managed_user.xml b/core/res/res/values-en-rAU/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-en-rAU/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 7a2e15a..700641e 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rCA/required_apps_managed_device.xml b/core/res/res/values-en-rCA/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-en-rCA/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rCA/required_apps_managed_profile.xml b/core/res/res/values-en-rCA/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-en-rCA/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rCA/required_apps_managed_user.xml b/core/res/res/values-en-rCA/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-en-rCA/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 7a2e15a..700641e 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/required_apps_managed_device.xml b/core/res/res/values-en-rGB/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-en-rGB/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rGB/required_apps_managed_profile.xml b/core/res/res/values-en-rGB/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-en-rGB/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rGB/required_apps_managed_user.xml b/core/res/res/values-en-rGB/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-en-rGB/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 7a2e15a..700641e 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/required_apps_managed_device.xml b/core/res/res/values-en-rIN/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-en-rIN/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rIN/required_apps_managed_profile.xml b/core/res/res/values-en-rIN/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-en-rIN/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rIN/required_apps_managed_user.xml b/core/res/res/values-en-rIN/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-en-rIN/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 7a2e15a..700641e 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rXC/required_apps_managed_device.xml b/core/res/res/values-en-rXC/required_apps_managed_device.xml
deleted file mode 100644
index 70d510f..0000000
--- a/core/res/res/values-en-rXC/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rXC/required_apps_managed_profile.xml b/core/res/res/values-en-rXC/required_apps_managed_profile.xml
deleted file mode 100644
index 9ca9960..0000000
--- a/core/res/res/values-en-rXC/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rXC/required_apps_managed_user.xml b/core/res/res/values-en-rXC/required_apps_managed_user.xml
deleted file mode 100644
index b2ef802..0000000
--- a/core/res/res/values-en-rXC/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 22da8ef..ba21245 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high quality saved network"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/required_apps_managed_device.xml b/core/res/res/values-es-rUS/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-es-rUS/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es-rUS/required_apps_managed_profile.xml b/core/res/res/values-es-rUS/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-es-rUS/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es-rUS/required_apps_managed_user.xml b/core/res/res/values-es-rUS/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-es-rUS/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 58268eb..1fe3c9a 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sin título>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Presiona para ver todas las redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas las redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Se activará la conexión Wi-Fi automáticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cuando estés cerca de una red guardada de alta calidad"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No volver a activar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Accede a una red Wi-Fi."</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Acceder a la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Error al restablecer el acceso directo porque la app no admite la opción de copia de seguridad y restauración"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Error al restablecer el acceso directo por falta de coincidencia con la firma de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Error al restablecer el acceso directo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/required_apps_managed_device.xml b/core/res/res/values-es/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-es/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es/required_apps_managed_profile.xml b/core/res/res/values-es/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-es/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es/required_apps_managed_user.xml b/core/res/res/values-es/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-es/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d03498c..cf25ed3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sin título>"</string>
@@ -449,7 +453,7 @@
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite que la aplicación se conecte a puntos de acceso Wi-Fi y se desconecte de ellos y que realice cambios en la configuración de redes Wi-Fi del dispositivo."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepción multidifusión Wi-Fi"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo al tablet. Utiliza más batería que el modo de no multidifusión."</string>
- <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos a través de una red Wi-Fi mediante direcciones de multidifusión, no solo la TV. Consume más energía que el modo sin multidifusión."</string>
+ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos a través de una red Wi-Fi mediante direcciones de multidifusión, no solo la TV. Consume más batería que el modo sin multidifusión."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo al teléfono. Utiliza más batería que el modo de no multidifusión."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acceder a los ajustes de Bluetooth"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure el tablet Bluetooth local y que detecte dispositivos remotos y se vincule con ellos."</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca para ver todas las redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectarse"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas las redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"La conexión Wi‑Fi se activará automáticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cuando estés cerca de una red de alta calidad guardada"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No volver a activar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sesión en red Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Iniciar sesión en la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"No se ha podido restaurar el acceso directo porque la aplicación no es compatible con la función de copia de seguridad y restauración"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"No se ha podido restaurar el acceso directo porque la firma de la aplicación no coincide"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"No se ha podido restaurar el acceso directo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/required_apps_managed_device.xml b/core/res/res/values-et/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-et/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-et/required_apps_managed_profile.xml b/core/res/res/values-et/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-et/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-et/required_apps_managed_user.xml b/core/res/res/values-et/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-et/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 754cdb3..c0821c7 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Pealkirjata>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Puudutage kõikide võrkude nägemiseks"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Ühenda"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Kõik võrgud"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WiFi lülitub sisse automaatselt"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kui olete kvaliteetse salvestatud võrgu läheduses"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ära lülita tagasi sisse"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logi sisse WiFi-võrku"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Võrku sisselogimine"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Otseteed ei õnnestunud taastada, kuna rakendus ei toeta varundamist ega taastamist"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Otseteed ei õnnestunud taastada, kuna rakenduse allkiri ei ühti"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Otseteed ei õnnestunud taastada"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/required_apps_managed_device.xml b/core/res/res/values-eu/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-eu/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-eu/required_apps_managed_profile.xml b/core/res/res/values-eu/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-eu/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-eu/required_apps_managed_user.xml b/core/res/res/values-eu/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-eu/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2e10fa2..100ed1e 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Izengabea>"</string>
@@ -290,7 +294,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Eskuratu leihoko edukia"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Arakatu irekita daukazun leihoko edukia."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktibatu \"Arakatu ukituta\""</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Sakatutako elementuak ozen esango dira eta pantaila keinu bidez arakatu ahal izango da."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Sakatutako elementuak ozen irakurriko dira eta pantaila keinu bidez arakatu ahal izango da."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Behatu idazten duzun testua"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Ez da salbuespenik egiten datu pertsonalekin, hala nola, kreditu-txartelen zenbakiekin eta pasahitzekin."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrolatu pantailaren zoom-maila"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Sakatu hau sare guztiak ikusteko"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Konektatu"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sare guztiak"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi konexioa automatikoki aktibatuko da"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Gordeta daukazun kalitate handiko sare batetik gertu zaudenean"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ez aktibatu berriro"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Hasi saioa Wi-Fi sarean"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Hasi saioa sarean"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1389,7 +1396,7 @@
<string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB unitatea"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB memoria"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editatu"</string>
- <string name="data_usage_warning_title" msgid="3620440638180218181">"Datuen erabilerari buruzko abisua"</string>
+ <string name="data_usage_warning_title" msgid="3620440638180218181">"Datuen erabilerari buruzko alerta"</string>
<string name="data_usage_warning_body" msgid="6660692274311972007">"Sakatu erabilera eta ezarpenak ikusteko."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2-3 GB-ko mugara iritsi zara"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4 GB-ko mugara iritsi zara"</string>
@@ -1500,8 +1507,8 @@
<string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea.\n\n Uneko erabilerraztasun-eginbidea:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Eginbidea aldatzeko, joan Ezarpenak > Erabilerraztasuna atalera."</string>
<string name="disable_accessibility_shortcut" msgid="627625354248453445">"Desaktibatu lasterbidea"</string>
<string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Erabili lasterbidea"</string>
- <string name="color_inversion_feature_name" msgid="4231186527799958644">"Koloreak alderantzikatzeko aukera"</string>
- <string name="color_correction_feature_name" msgid="6779391426096954933">"Kolorearen zuzenketa"</string>
+ <string name="color_inversion_feature_name" msgid="4231186527799958644">"Koloreen alderantzikatzea"</string>
+ <string name="color_correction_feature_name" msgid="6779391426096954933">"Koloreen zuzenketa"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"Erabilerraztasun-lasterbideak <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu du"</string>
<string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"Erabilerraztasun-lasterbideak <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu du"</string>
<string name="accessibility_button_prompt_text" msgid="4234556536456854251">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoia sakatzean:"</string>
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ezin izan da leheneratu lasterbidea aplikazioak ez duelako onartzen babeskopiak egiteko eta leheneratzeko aukera"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ezin izan da leheneratu lasterbidea aplikazioaren sinadurak ez datozelako bat"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ezin izan da leheneratu lasterbidea"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/required_apps_managed_device.xml b/core/res/res/values-fa/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-fa/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fa/required_apps_managed_profile.xml b/core/res/res/values-fa/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-fa/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fa/required_apps_managed_user.xml b/core/res/res/values-fa/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-fa/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dfa350b..0458336 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"بایت"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"کیلوبایت"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"مگابایت"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"گیگابایت"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
<string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<بدون عنوان>"</string>
@@ -453,7 +457,7 @@
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه میدهد به دریافت بستههای ارسالی به همه دستگاههای موجود در شبکه Wi-Fi با استفاده از آدرسهای پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده میکند."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه میدهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها مرتبطسازی شود."</string>
- <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"به برنامه اجازه میدهد تا تلویزیون بلوتوث محلی را پیکربندی کند و دستگاههای از راه دور را شناسایی کند و با آنها مرتبط شود."</string>
+ <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"به برنامه اجازه میدهد تا تلویزیون بلوتوث محلی را پیکربندی کند و دستگاههای ازراهدور را شناسایی کند و با آنها مرتبط شود."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه میدهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاههای راه دور را پیدا کند و با آنها مرتبطسازی شود."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"اتصال و قطع اتصال از WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان میدهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکههای وایمکس متصل را مشخص کند."</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"برای دیدن همه شبکهها ضربه بزنید"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"اتصال"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"همه شبکهها"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi بهطور خودکار روشن خواهد شد"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"وقتی نزدیک شبکه ذخیرهشده با کیفیت بالا هستید"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"دوباره روشن نشود"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ورود به شبکه Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ورود به سیستم شبکه"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"نمیتوان میانبر را بازیابی کرد زیرا برنامه از پشتیبانگیری و بازیابی پشتیبانی نمیکند"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"بهعلت عدم تطابق امضای برنامه نمیتوان میانبر را بازیابی کرد"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"نمیتوان میانبر را بازیابی کرد"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/required_apps_managed_device.xml b/core/res/res/values-fi/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-fi/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fi/required_apps_managed_profile.xml b/core/res/res/values-fi/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-fi/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fi/required_apps_managed_user.xml b/core/res/res/values-fi/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-fi/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5696b5a..d6d1315 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"t"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kt"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Mt"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"Gt"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"Tt"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Pt"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Nimetön>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Napauta, niin näet kaikki verkot."</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Yhdistä"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Kaikki verkot"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi käynnistyy automaattisesti"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kun olet lähellä laadukasta tallennettua verkkoa"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Älä käynnistä uudelleen"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kirjaudu Wi-Fi-verkkoon"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Kirjaudu verkkoon"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Pikakuvakkeen palautus epäonnistui, koska sovellus ei tue varmuuskopiointia eikä palauttamista."</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Pikakuvakkeen palautus epäonnistui sovelluksen allekirjoituksen yhteensopimattomuuden vuoksi."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Pikakuvakkeen palautus epäonnistui."</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/required_apps_managed_device.xml b/core/res/res/values-fr-rCA/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-fr-rCA/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr-rCA/required_apps_managed_profile.xml b/core/res/res/values-fr-rCA/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-fr-rCA/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr-rCA/required_apps_managed_user.xml b/core/res/res/values-fr-rCA/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-fr-rCA/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6e97844..9af3ed7 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"o"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"ko"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Mo"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"Go"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"To"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sans_titre>"</string>
@@ -982,7 +986,7 @@
<string name="email" msgid="4560673117055050403">"Courriel"</string>
<string name="dial" msgid="1253998302767701559">"Appel"</string>
<string name="map" msgid="6521159124535543457">"Localiser"</string>
- <string name="browse" msgid="1245903488306147205">"Ouvert"</string>
+ <string name="browse" msgid="1245903488306147205">"Ouvrir"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Ajouter"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"Espace de stockage bientôt saturé"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Touchez pour afficher tous les réseaux"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connexion"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tous les réseaux"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Le Wi-Fi s\'activera automatiquement"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Lorsque vous êtes près d\'un réseau enregistré de haute qualité"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne pas réactiver"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Connectez-vous au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Impossible de restaurer le raccourci, car l\'application ne prend pas en charge la sauvegarde et la restauration"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Impossible de restaurer le raccourci en raison d\'une erreur de correspondance des signature d\'applications"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossible de restaurer le raccourci"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/required_apps_managed_device.xml b/core/res/res/values-fr/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-fr/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr/required_apps_managed_profile.xml b/core/res/res/values-fr/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-fr/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr/required_apps_managed_user.xml b/core/res/res/values-fr/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-fr/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7dc33c4..97cc0ec 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"octet(s)"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"Ko"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Mo"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"Go"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"To"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sans nom>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Appuyer pour afficher tous les réseaux"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Se connecter"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tous les réseaux"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Le Wi-Fi sera activé automatiquement"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Lorsque vous êtes à proximité d\'un réseau enregistré de haute qualité"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne pas réactiver"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Se connecter au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1215,7 +1222,7 @@
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Afficher par-dessus les autres applications"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> est affichée sur les autres applications"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'affiche sur autres applis"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se superpose aux autres applis"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DÉSACTIVER"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Préparation mémoire \"<xliff:g id="NAME">%s</xliff:g>\" en cours"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Le raccourci ne peut pas être restauré car l\'application n\'accepte pas la sauvegarde et la restauration"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Le raccourci ne peut pas être restauré car la signature de l\'application est différente"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossible de restaurer le raccourci"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/required_apps_managed_device.xml b/core/res/res/values-gl/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-gl/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gl/required_apps_managed_profile.xml b/core/res/res/values-gl/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-gl/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gl/required_apps_managed_user.xml b/core/res/res/values-gl/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-gl/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index b4e3904..a53fac7 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sen título>"</string>
@@ -129,7 +133,7 @@
<string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivado"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wifi preferida"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Datos móbiles preferidos"</string>
- <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Só wifi"</string>
+ <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Só por wifi"</string>
<string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non desviada"</string>
<string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> tras <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca para ver todas as redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectarse"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"A wifi activarase automaticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cando esteas preto dunha rede gardada de alta calidade"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Non volver activar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia sesión na rede wifi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia sesión na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Non se puido restaurar o atallo porque a aplicación non é compatible coa restauración e a copia de seguranza"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Non se puido restaurar o atallo porque a sinatura da aplicación non coincide"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Non se puido restaurar o atallo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/required_apps_managed_device.xml b/core/res/res/values-gu/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-gu/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gu/required_apps_managed_profile.xml b/core/res/res/values-gu/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-gu/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gu/required_apps_managed_user.xml b/core/res/res/values-gu/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-gu/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index eada633..81e5f4f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<અનામાંકિત>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"બધા નેટવર્ક જોવા ટૅપ કરો"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"કનેક્ટ કરો"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"બધા નેટવર્ક"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"વાઇ-ફાઇ આપમેળે ચાલુ થઈ જશે"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"જ્યારે તમે એક ઉચ્ચ ક્વૉલિટીવાળા સાચવેલ નેટવર્કની નજીક હોવ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"પાછું ચાલુ કરશો નહીં"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"નેટવર્ક પર સાઇન ઇન કરો"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાનું સમર્થન કરતી નથી"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપમાં છે તે સહી મેળ ખાતી નથી"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"શૉર્ટકટ પાછો મેળવી શકાયો નથી"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/required_apps_managed_device.xml b/core/res/res/values-hi/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-hi/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hi/required_apps_managed_profile.xml b/core/res/res/values-hi/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-hi/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hi/required_apps_managed_user.xml b/core/res/res/values-hi/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-hi/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f9e8a03..2349583 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"केबी"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"एमबी"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"जीबी"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<शीर्षक-रहित>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सभी नेटवर्क देखने के लिए यहां पर टैप करें"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"कनेक्ट करें"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सभी नेटवर्क"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"वाई-फ़ाई अपने आप चालू हो जाएगा"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"जब आप किसी अच्छी क्वालिटी वाले सेव किए गए नेटवर्क के पास हों"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"वापस चालू न करें"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"वाई-फ़ाई नेटवर्क में साइन इन करें"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्क में साइन इन करें"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"शॉर्टकट बहाल नहीं किया जा सका क्योंकि इस ऐप में बैकअप लेने और उसे बहाल करने की सुविधा नहीं है"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ऐप सिग्नेचर अलग होने के कारण शॉर्टकट बहाल नहीं किया जा सका"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"शॉर्टकट बहाल नहीं किया जा सका"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/required_apps_managed_device.xml b/core/res/res/values-hr/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-hr/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hr/required_apps_managed_profile.xml b/core/res/res/values-hr/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-hr/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hr/required_apps_managed_user.xml b/core/res/res/values-hr/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-hr/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7e53209..bbe7ca9 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez naslova>"</string>
@@ -1138,6 +1142,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite za prikaz svih mreža"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Poveži"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi će se uključiti automatski"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini spremljene mreže visoke kvalitete"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Više ne uključuj"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijava na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1835,4 +1842,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Vraćanje prečaca nije uspjelo jer aplikacija ne podržava sigurnosno kopiranje i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Vraćanje prečaca nije uspjelo zbog nepodudaranja potpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Vraćanje prečaca nije uspjelo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/required_apps_managed_device.xml b/core/res/res/values-hu/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-hu/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hu/required_apps_managed_profile.xml b/core/res/res/values-hu/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-hu/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hu/required_apps_managed_user.xml b/core/res/res/values-hu/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-hu/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b815035..2dbe49d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Névtelen>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Koppintással megjelenítheti az összes hálózatot"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Kapcsolódás"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Összes hálózat"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"A Wi-Fi automatikusan bekapcsol"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Amikor jó minőségű mentett hálózat közelében tartózkodik"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne kapcsolódjon vissza"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Bejelentkezés Wi-Fi hálózatba"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Bejelentkezés a hálózatba"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nem sikerült visszaállítani a parancsikont, mert az alkalmazás nem támogatja a biztonsági mentést és visszaállítást"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nem sikerült visszaállítani a parancsikont, mert az alkalmazás-aláírás nem egyezik"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nem sikerült visszaállítani a parancsikont"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/required_apps_managed_device.xml b/core/res/res/values-hy/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-hy/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hy/required_apps_managed_profile.xml b/core/res/res/values-hy/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-hy/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hy/required_apps_managed_user.xml b/core/res/res/values-hy/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-hy/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index ff615c50..1218b48 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Բ"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"ԿԲ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"ՄԲ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ԳԲ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ՏԲ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Պբ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Անանուն>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Հպեք՝ բոլոր ցանցերը տեսնելու համար"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Միանալ"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Բոլոր ցանցերը"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi-ն ավտոմատ կմիանա"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Լավ ազդանշանով պահված ցանցի տարածքում գտնվելիս"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Նորից չմիացնել"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Մուտք գործեք Wi-Fi ցանց"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Մուտք գործեք ցանց"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածում չի աջակցվում պահուստավորման և վերականգնման գործառույթը"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածների ստորագրությունները տարբեր են"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Չհաջողվեց վերականգնել դյուրանցումը"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/required_apps_managed_device.xml b/core/res/res/values-in/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-in/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-in/required_apps_managed_profile.xml b/core/res/res/values-in/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-in/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-in/required_apps_managed_user.xml b/core/res/res/values-in/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-in/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b8b76a0..cb2b8a5 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Tanpa judul>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap untuk melihat semua jaringan"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Hubungkan"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Semua Jaringan"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi akan aktif otomatis"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Saat berada di dekat jaringan berkualitas tinggi yang tersimpan"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Jangan aktifkan kembali"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Masuk ke jaringan Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Masuk ke jaringan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Tidak dapat memulihkan pintasan karena aplikasi tidak mendukung backup dan pulihkan"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tidak dapat memulihkan pintasan karena tanda tangan aplikasi tidak cocok"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Tidak dapat memulihkan pintasan."</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/required_apps_managed_device.xml b/core/res/res/values-is/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-is/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-is/required_apps_managed_profile.xml b/core/res/res/values-is/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-is/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-is/required_apps_managed_user.xml b/core/res/res/values-is/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-is/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 76286e1..40bf34c 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Ónefnt>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Ýttu til að sjá öll netkerfi"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Tengjast"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Öll netkerfi"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Kveikt verður sjálfkrafa á Wi‑Fi"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Þegar þú ert nálægt vistuðu hágæðaneti"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ekki kveikja aftur"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Skrá inn á Wi-Fi net"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Skrá inn á net"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ekki var hægt að endurheimta flýtileið vegna þess að forritið styður ekki öryggisafritun og endurheimt"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ekki var hægt að endurheimta flýtileið vegna þess að undirskriftir forrita passa ekki saman"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ekki var hægt að endurheimta flýtileið"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/required_apps_managed_device.xml b/core/res/res/values-it/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-it/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-it/required_apps_managed_profile.xml b/core/res/res/values-it/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-it/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-it/required_apps_managed_user.xml b/core/res/res/values-it/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-it/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7e96aff..3c9745f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Senza nome>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tocca per vedere tutte le reti"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Connetti"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tutte le reti"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Il Wi‑Fi verrà attivato automaticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando ti trovi nell\'area di una rete salvata di alta qualità"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Non riattivare"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Accedi a rete Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Accedi alla rete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Impossibile ripristinare la scorciatoia perché l\'app non supporta il backup e il ripristino"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Impossibile ripristinare la scorciatoia perché la firma dell\'app non corrisponde"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossibile ripristinare la scorciatoia"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/required_apps_managed_device.xml b/core/res/res/values-iw/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-iw/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-iw/required_apps_managed_profile.xml b/core/res/res/values-iw/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-iw/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-iw/required_apps_managed_user.xml b/core/res/res/values-iw/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-iw/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 87e20c0..7c0ce3a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">">ללא כותרת<"</string>
@@ -531,8 +535,8 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"מאפשר לאפליקציה לנהל מדיניות הרשת להגדיר כללים ספציפיים-לאפליקציה."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"שנה ניהול חשבונות של שימוש ברשת"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"הרשאה זו מאפשרת לאפליקציה לשנות את אופן החישוב של נתוני שימוש ברשת מול כל אפליקציה. לא מיועד לשימוש באפליקציות רגילות."</string>
- <string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להתראות"</string>
- <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
+ <string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להודעות"</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק הודעות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"איגוד לשירות של מאזין להתראות"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של שירות מאזין להתראות. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"איגוד לשירות ספק תנאי"</string>
@@ -1127,13 +1131,13 @@
<string name="volume_call" msgid="3941680041282788711">"עוצמת קול בשיחה"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"עוצמת הקול בשיחה ב-Bluetooth"</string>
<string name="volume_alarm" msgid="1985191616042689100">"עוצמת קול של התראה"</string>
- <string name="volume_notification" msgid="2422265656744276715">"עוצמת קול של התראות"</string>
+ <string name="volume_notification" msgid="2422265656744276715">"עוצמת קול של הודעות"</string>
<string name="volume_unknown" msgid="1400219669770445902">"עוצמת קול"</string>
<string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"עוצמת קול של Bluetooth"</string>
<string name="volume_icon_description_ringer" msgid="3326003847006162496">"עוצמת קול של רינגטון"</string>
<string name="volume_icon_description_incall" msgid="8890073218154543397">"עוצמת קול של שיחות"</string>
<string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string>
- <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
+ <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של הודעות"</string>
<string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
<string name="ringtone_default_with_actual" msgid="1767304850491060581">"ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"יש להקיש כדי לראות את כל הרשתות"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"התחבר"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"כל הרשתות"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ה-Wi-Fi יופעל אוטומטית"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"כשתימצאו בקרבת רשת באיכות גבוהה ששמרתם"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"אל תפעיל שוב"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"היכנס לרשת Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"היכנס לרשת"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"לא ניתן היה לשחזר את קיצור הדרך מפני שהאפליקציה אינה תומכת בגיבוי ובשחזור"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"לא ניתן היה לשחזר את קיצור הדרך עקב חוסר התאמה בחתימה על האפליקציות"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"לא ניתן היה לשחזר את קיצור הדרך"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/required_apps_managed_device.xml b/core/res/res/values-ja/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ja/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ja/required_apps_managed_profile.xml b/core/res/res/values-ja/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ja/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ja/required_apps_managed_user.xml b/core/res/res/values-ja/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ja/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index c2cc154..2fb35f8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<新規>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"すべてのネットワークを表示するにはタップします"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"接続"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"すべてのネットワーク"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi は自動的にオンになります"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"高品質の保存済みネットワークの検出時"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"再度オンにしない"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fiネットワークにログイン"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ネットワークにログインしてください"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"このアプリはバックアップと復元に対応していないため、ショートカットを復元できませんでした"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"アプリの署名が一致しないため、ショートカットを復元できませんでした"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ショートカットを復元できませんでした"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/required_apps_managed_device.xml b/core/res/res/values-ka/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ka/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ka/required_apps_managed_profile.xml b/core/res/res/values-ka/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ka/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ka/required_apps_managed_user.xml b/core/res/res/values-ka/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ka/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index ae4fb6f..45ed466 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"ბაიტი"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"კბაიტი"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"მბაიტი"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"გბაიტი"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ტბაიტი"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"უსათაურო"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"შეეხეთ ყველა ქსელის სანახავად"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"დაკავშირება"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ყველა ქსელი"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi ავტომატურად ჩაირთვება"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"როცა შენახულ მაღალხარისხიან ქსელებთან ახლოს იმყოფებით"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ხელახლა ნუ ჩართავ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ქსელთან დაკავშირება"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ქსელში შესვლა"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"მალსახმობის აღდგენა ვერ მოხერხდა, რადგან ამ აპის მიერ მხარდაუჭერელია სარეზერვო ასლით აღდგენა"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"მალსახმობის აღდგენა ვერ მოხერხდა აპის ხელმოწერის შეუსაბამობის გამო"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"მალსახმობის აღდგენა ვერ მოხერხდა"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk/required_apps_managed_device.xml b/core/res/res/values-kk/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-kk/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kk/required_apps_managed_profile.xml b/core/res/res/values-kk/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-kk/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kk/required_apps_managed_user.xml b/core/res/res/values-kk/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-kk/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index d56e6df..51c5147 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Атаусыз>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Барлық желілерді көру үшін түртіңіз"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Қосылу"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Барлық желілер"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi автоматты түрде қосылады"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Сақталған жоғары сапалы желіге жақын болғанда"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Қайта қоспау"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi желісіне кіру"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Желіге кіру"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Қолданба сақтық көшірме жасау мен қалпына келтіруді қолдамайтындықтан, таңбаша қалпына келтірілмеді"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Қолтаңба сәйкес келмейтіндіктен, таңбаша қалпына келтірілмеді"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Таңбаша қалпына келтірілмеді"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/required_apps_managed_device.xml b/core/res/res/values-km/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-km/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-km/required_apps_managed_profile.xml b/core/res/res/values-km/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-km/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-km/required_apps_managed_user.xml b/core/res/res/values-km/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-km/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 7be15f1..c266416 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"មេកាបៃ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ជីកាបៃ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"តេរ៉ាបៃ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<គ្មានចំណងជើង>"</string>
@@ -1118,6 +1122,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ចុចដើម្បីមើលបណ្តាញទាំងអស់"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"ភ្ជាប់"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"បណ្តាញទាំងអស់"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi នឹងបើកដោយស្វ័យប្រវត្តិ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"នៅពេលដែលអ្នកនៅជិតបណ្តាញគុណភាពខ្ពស់ដែលបានរក្សាទុក"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"កុំបើកឡើងវិញ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ចូលបណ្ដាញវ៉ាយហ្វាយ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ចូលទៅបណ្តាញ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1802,4 +1809,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"មិនអាចស្តារផ្លូវកាត់បានទេ ដោយសារកម្មវិធីមិនស្គាល់ការបម្រុងទុក និងការស្តារ"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"មិនអាចស្តារផ្លូវកាត់បានទេ ដោយសារការស៊ីញ៉េកម្មវិធីមិនត្រូវគ្នា"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"មិនអាចស្តារផ្លូវកាត់បានទេ"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/required_apps_managed_device.xml b/core/res/res/values-kn/required_apps_managed_device.xml
deleted file mode 100644
index e15b0b0..0000000
--- a/core/res/res/values-kn/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.ಸೆಟ್ಟಿಂಗ್ಗಳು"</item>
- <item msgid="7004798084799227194">"com.android.ಸಂಪರ್ಕಗಳು"</item>
- <item msgid="5782220690863647256">"com.android.ಡಯಲರ್"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.ಒದಗಿಸುವವರು.ಡೌನ್ಲೋಡ್ಗಳು"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kn/required_apps_managed_profile.xml b/core/res/res/values-kn/required_apps_managed_profile.xml
deleted file mode 100644
index 92ab682..0000000
--- a/core/res/res/values-kn/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.ಸಂಪರ್ಕಗಳು"</item>
- <item msgid="4633145750237794002">"com.android.ಸೆಟ್ಟಿಂಗ್ಗಳು"</item>
- <item msgid="6518205098643077579">"com.android.ಒದಗಿಸುವವರು.ಡೌನ್ಲೋಡ್ಗಳು"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kn/required_apps_managed_user.xml b/core/res/res/values-kn/required_apps_managed_user.xml
deleted file mode 100644
index 0c59edd..0000000
--- a/core/res/res/values-kn/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.ಸೆಟ್ಟಿಂಗ್ಗಳು"</item>
- <item msgid="2250259015310893915">"com.android.ಸಂಪರ್ಕಗಳು"</item>
- <item msgid="7166574999426592423">"com.android.ಡಯಲರ್"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.ಒದಗಿಸುವವರು.ಡೌನ್ಲೋಡ್ಗಳು"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 99db9e6..2fe14dc 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ಶೀರ್ಷಿಕೆ ರಹಿತ>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ಎಲ್ಲಾ ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"ಸಂಪರ್ಕಿಸಿ"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ಎಲ್ಲಾ ನೆಟ್ವರ್ಕ್ಗಳು"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ವೈ‑ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗುತ್ತದೆ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ನೀವು ಉಳಿಸಿದ ಅಧಿಕ ಗುಣಮಟ್ಟದ ನೆಟ್ವರ್ಕ್ ಸಮೀಪದಲ್ಲಿದ್ದಾಗ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ಮತ್ತೆ ಆನ್ ಮಾಡಲು ಹಿಂತಿರುಗಬೇಡಿ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"ಅಪ್ಲಿಕೇಶನ್ ಬ್ಯಾಕಪ್ ಮತ್ತು ಪುನಃಸ್ಥಾಪನೆಯನ್ನು ಬೆಂಬಲಿಸದಿರುವುದರಿಂದ ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಪುನಃಸ್ಥಾಪನೆ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ಅಪ್ಲಿಕೇಶನ್ ಸಹಿ ಹೊಂದಿಕೆಯಾಗದ ಕಾರಣದಿಂದ ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಪುನಃಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಪುನಃ ಸ್ಥಾಪನೆ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/required_apps_managed_device.xml b/core/res/res/values-ko/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ko/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ko/required_apps_managed_profile.xml b/core/res/res/values-ko/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ko/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ko/required_apps_managed_user.xml b/core/res/res/values-ko/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ko/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 650d980..221a233 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<제목 없음>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"모든 네트워크를 보려면 탭하세요."</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"연결"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"모든 네트워크"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi가 자동으로 사용 설정됨"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"저장된 고품질 네트워크가 가까이 있는 경우"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"다시 사용 설정하지 않음"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi 네트워크에 로그인"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"네트워크에 로그인"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"앱이 백업 및 복원을 지원하지 않으므로 바로가기를 복원할 수 없습니다"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"앱 서명이 일치하지 않아 바로가기를 복원할 수 없습니다"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"바로가기를 복원할 수 없습니다"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/required_apps_managed_device.xml b/core/res/res/values-ky/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ky/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ky/required_apps_managed_profile.xml b/core/res/res/values-ky/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ky/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ky/required_apps_managed_user.xml b/core/res/res/values-ky/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ky/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index cfa05de..1bce491 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"Кб"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"Мб"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"Гб"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Баш аты жок>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Бардык тармактарды көрүү үчүн басыңыз"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Туташуу"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Бардык тармактар"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi автоматтык түрдө күйгүзүлөт"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Байланыш сигналы жакшы болгон тармактарга жакындаганда"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Өзү кайра күйбөйт"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi түйүнүнө кирүү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Тармакка кирүү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1802,4 +1809,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Колдонмо камдык көчүрмөнү сактоо жана калыбына келтирүү функцияларын колдобогондуктан кыска жол калыбына келтирилбей койду"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Колдонмонун колтамгасы дал келбегендиктен кыска жол калыбына келтирилбей койду"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Кыска жол калыбына келтирилбей койду"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/required_apps_managed_device.xml b/core/res/res/values-lo/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-lo/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lo/required_apps_managed_profile.xml b/core/res/res/values-lo/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-lo/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lo/required_apps_managed_user.xml b/core/res/res/values-lo/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-lo/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index feedbf3..9f7a28f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ບໍ່ມີຊື່>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ແຕະເພື່ອເບິ່ງເຄືອຂ່າຍທັງໝົດ"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"ເຊື່ອມຕໍ່"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ເຄືອຂ່າຍທັງໝົດ"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ຈະມີການເປີດໃຊ້ Wi‑Fi ອັດຕະໂນມັດ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ເມື່ອທ່ານຢູ່ໃກ້ເຄືອຂ່າຍຄຸນນະພາບສູງທີ່ບັນທຶກໄວ້"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ບໍ່ຕ້ອງເປີດໃຊ້ຄືນໃໝ່"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ລົງຊື່ເຂົ້າເຄືອຂ່າຍ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"ບໍ່ສາມາດກູ້ທາງລັດຂຶ້ນມາໄດ້ເນື່ອງຈາກແອັບບໍ່ຮອງຮັບການສຳຮອງ ແລະ ກູ້ຂໍ້ມູນ"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ບໍ່ສາມາດກູ້ທາງລັດຄືນມາໄດ້ເນື່ອງຈາກລາຍເຊັນແອັບບໍ່ກົງກັນ"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ບໍ່ສາມາດກູ້ທາງລັດຄືນມາໄດ້"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/required_apps_managed_device.xml b/core/res/res/values-lt/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-lt/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lt/required_apps_managed_profile.xml b/core/res/res/values-lt/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-lt/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lt/required_apps_managed_user.xml b/core/res/res/values-lt/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-lt/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 95e4862..57745c2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Be pavadinimo>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Palieskite, jei norite matyti visus tinklus"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Prisijungti"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Visi tinklai"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"„Wi‑Fi“ bus įjungtas automatiškai"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kai būsite netoli išsaugoto aukštos kokybės tinklo"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Neįjunkite vėl"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prisijungti prie „Wi-Fi“ tinklo"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prisijungti prie tinklo"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nepavyko atkurti sparčiojo klavišo, nes programa nepalaiko atsarginės kopijos kūrimo ir atkūrimo funkcijų"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nepavyko atkurti sparčiojo klavišo, nes programos parašas neatitinka"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nepavyko atkurti sparčiojo klavišo"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/required_apps_managed_device.xml b/core/res/res/values-lv/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-lv/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lv/required_apps_managed_profile.xml b/core/res/res/values-lv/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-lv/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lv/required_apps_managed_user.xml b/core/res/res/values-lv/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-lv/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 12bb04b..2d98ade 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez nosaukuma>"</string>
@@ -1138,6 +1142,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Pieskarieties, lai skatītu visus tīklus"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Izveidot savienojumu"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Visi tīkli"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi tiks automātiski ieslēgts"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kad atrodaties saglabāta augstas kvalitātes tīkla tuvumā"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Neieslēgt atkārtoti"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Pierakstieties Wi-Fi tīklā"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Pierakstīšanās tīklā"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1835,4 +1842,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nevarēja atjaunot saīsni, jo lietotnē netiek atbalstīta dublēšana un atjaunošana."</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Saīsni nevarēja atjaunot lietotnes paraksta neatbilstības dēļ."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nevarēja atjaunot saīsni."</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk/required_apps_managed_device.xml b/core/res/res/values-mk/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-mk/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mk/required_apps_managed_profile.xml b/core/res/res/values-mk/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-mk/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mk/required_apps_managed_user.xml b/core/res/res/values-mk/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-mk/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index c5773f8..67aabea 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без наслов>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Допрете за да ги видите сите мрежи"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Поврзете се"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Сите мрежи"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ќе се вклучи автоматски"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Кога сте во близина на зачувана мрежа со висок квалитет"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не вклучувај повторно"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Најавете се на мрежа на Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Најавете се на мрежа"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1803,4 +1810,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Не можеше да се врати кратенката бидејќи апликацијата не поддржува бекап и враќање"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Не можеше да се врати кратенката бидејќи потписот на апликацијата не се совпаѓа"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Не можеше да се врати кратенката"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/required_apps_managed_device.xml b/core/res/res/values-ml/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ml/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ml/required_apps_managed_profile.xml b/core/res/res/values-ml/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ml/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ml/required_apps_managed_user.xml b/core/res/res/values-ml/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ml/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index fc958fa..69c0fed 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ശീർഷകമില്ലാത്ത>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"എല്ലാ നെറ്റ്വർക്കുകളും കാണാൻ ടാപ്പുചെയ്യുക"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"കണക്റ്റുചെയ്യുക"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"എല്ലാ നെറ്റ്വർക്കുകളും"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"വൈഫൈ സ്വമേധയാ ഓണാകും"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"നിങ്ങൾ ഉയർന്ന നിലവാരമുള്ള സംരക്ഷിക്കപ്പെട്ട നെറ്റ്വർക്കിനരികിലെത്തുമ്പോൾ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"തിരികെ ഓണാക്കരുത്"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"വൈഫൈ നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"ആപ്പ് \'ബാക്കപ്പും പുനഃസ്ഥാപിക്കലും\' പിന്തുണയ്ക്കാത്തതിനാൽ കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ആപ്പ് സിഗ്നേച്ചർ പൊരുത്തപ്പെടാത്തതിനാൽ കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"കുറുക്കുവഴി പുനഃസ്ഥാപിക്കാനായില്ല"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/required_apps_managed_device.xml b/core/res/res/values-mn/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-mn/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mn/required_apps_managed_profile.xml b/core/res/res/values-mn/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-mn/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mn/required_apps_managed_user.xml b/core/res/res/values-mn/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-mn/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 9f26a3b..dbbb29e 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"килобайт"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Гарчиггүй>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Бүх сүлжээг харахын тулд товшино уу"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Холбогдох"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Бүх сүлжээ"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi автоматаар асна"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Таныг хадгалсан, өндөр чанартай сүлжээний ойролцоо байх үед"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Буцааж асаахгүй"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Сүлжээнд нэвтэрнэ үү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1798,4 +1805,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Апп нөөцлөлт, сэргээлтийг дэмждэггүй тул товчлолыг сэргээж чадсангүй"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Аппын гарын үсэг таарахгүй байгаа тул товчлолыг сэргээж чадсангүй"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Товчлолыг сэргээж чадсангүй"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/required_apps_managed_device.xml b/core/res/res/values-mr/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-mr/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mr/required_apps_managed_profile.xml b/core/res/res/values-mr/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-mr/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mr/required_apps_managed_user.xml b/core/res/res/values-mr/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-mr/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a757849..addb2d1 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<अशीर्षकांकित>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सर्व नेटवर्क पाहण्यासाठी टॅप करा"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"कनेक्ट करा"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सर्व नेटवर्क"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"वाय-फाय आपोआप चालू होईल"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"तुम्ही जेव्हा सेव्ह केलेल्या उच्च दर्जाच्या नेटवर्कजवळ असाल तेव्हा"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"पुन्हा चालू करू नका"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"वाय-फाय नेटवर्कमध्ये साइन इन करा"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्कवर साइन इन करा"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1601,7 +1608,7 @@
<string name="write_fail_reason_cancelled" msgid="7091258378121627624">"रद्द केले"</string>
<string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"आशय लिहिण्यात एरर"</string>
<string name="reason_unknown" msgid="6048913880184628119">"अज्ञात"</string>
- <string name="reason_service_unavailable" msgid="7824008732243903268">"मुद्रण सेवा सक्षम केली नाही"</string>
+ <string name="reason_service_unavailable" msgid="7824008732243903268">"प्रिंट सेवा सक्षम केली नाही"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> सेवा स्थापित केली"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"सक्षम करण्यासाठी टॅप करा"</string>
<string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"प्रशासक पिन एंटर करा"</string>
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"अॅप बॅकअप आणि रिस्टोअर करण्यास सपोर्ट देत नसल्यामुळे शॉर्टकट रिस्टोअर करू शकलो नाही"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"अॅप स्वाक्षरी न जुळल्यामुळे शॉर्टकट रिस्टोअर करू शकलो नाही"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"शॉर्टकट रिस्टोअर करू शकलो नाही"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/required_apps_managed_device.xml b/core/res/res/values-ms/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ms/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ms/required_apps_managed_profile.xml b/core/res/res/values-ms/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ms/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ms/required_apps_managed_user.xml b/core/res/res/values-ms/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ms/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index aee2000..f7e18ff 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B."</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Tidak bertajuk>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Ketik untuk melihat semua rangkaian"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Sambung"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Semua Rangkaian"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi akan dihidupkan secara automatik"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Apabila anda berada berdekatan dengan rangkaian disimpan yang berkualiti tinggi"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Jangan hidupkan kembali"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log masuk ke rangkaian Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log masuk ke rangkaian"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Tidak dapat memulihkan pintasan kerana apl tidak menyokong sandaran dan segerakan"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tidak dapat memulihkan pintasan kerana ketakpadanan tandatangan apl"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Tidak dapat memulihkan pintasan"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/required_apps_managed_device.xml b/core/res/res/values-my/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-my/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-my/required_apps_managed_profile.xml b/core/res/res/values-my/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-my/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-my/required_apps_managed_user.xml b/core/res/res/values-my/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-my/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index fec37ab..1777b26 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ခေါင်းစဉ်မဲ့>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ကွန်ရက်အားလုံးကို ကြည့်ရန် တို့ပါ"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"ချိတ်ဆက်ရန်"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ကွန်ရက်အားလုံး"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ကို အလိုအလျောက် ပြန်ဖွင့်ပေးလိမ့်ပါမည်"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"သိမ်းဆည်းထားသည့် အရည်အသွေးမြင့်ကွန်ရက်များအနီးသို့ ရောက်ရှိသည့်အခါ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ပြန်မဖွင့်ပါနှင့်"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"အက်ပ်သည် မိတ္တူကူးခြင်းနှင့် ပြန်ယူခြင်းကို ပံ့ပိုးခြင်းမရှိသည့်အတွက် ဖြတ်လမ်းလင့်ခ်ကို ပြန်ယူ၍မရပါ"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"အက်ပ်လက်မှတ် မတူညီသည့်အတွက် ဖြတ်လမ်းလင့်ခ်များကို ပြန်ယူ၍မရပါ"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ဖြတ်လမ်းလင့်ခ်ကို ပြန်ယူ၍မရပါ"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/required_apps_managed_device.xml b/core/res/res/values-nb/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-nb/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nb/required_apps_managed_profile.xml b/core/res/res/values-nb/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-nb/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nb/required_apps_managed_user.xml b/core/res/res/values-nb/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-nb/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 915701c..873967a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Uten navn>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Trykk for å se alle nettverkene"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Koble til"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle nettverk"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi slås på automatisk"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Når du er i nærheten av et lagret nettverk av høy kvalitet"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ikke slå på igjen"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logg på Wi-Fi-nettverket"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logg på nettverk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kunne ikke gjenopprette snarveien fordi appen ikke støtter sikkerhetskopiering og gjenoppretting"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kunne ikke gjenopprette snarveien på grunn av manglende samsvar for appsignaturen"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kunne ikke gjenopprette snarveien"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/required_apps_managed_device.xml b/core/res/res/values-ne/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ne/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ne/required_apps_managed_profile.xml b/core/res/res/values-ne/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ne/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ne/required_apps_managed_user.xml b/core/res/res/values-ne/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ne/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index f0a45a3..3e0e04b 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"के.बि."</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<बिना शीर्षक>"</string>
@@ -378,9 +382,9 @@
<string name="permlab_bodySensors" msgid="4683341291818520277">"शरीरका सेन्सरहरूमा पहुँच गराउनुहोस् (जस्तै हृदय धड्कन निगरानीहरू)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"तपाईँको हृदय गति जस्तो सेंसर बाट डेटा पहुँचको लागि अनुप्रयोग अनुमति दिन्छ जसले तपाईँको भौतिक अवस्था अनुगमन गर्छ।"</string>
<string name="permlab_readCalendar" msgid="6716116972752441641">"पात्रोका कार्यक्रम र विवरणहरू पढ्ने"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"यस अनुप्रयोगले तपाईंको ट्याब्लेटमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान-प्रदान वा सुरक्षित गर्न सक्छ।"</string>
- <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"यस अनुप्रयोगले तपाईंको TV मा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान-प्रदान वा सुरक्षित गर्न सक्छ।"</string>
- <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"यस अनुप्रयोगले तपाईंको फोनमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान-प्रदान वा सुरक्षित गर्न सक्छ।"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"यस अनुप्रयोगले तपाईंको ट्याब्लेटमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"यस अनुप्रयोगले तपाईंको TV मा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
+ <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"यस अनुप्रयोगले तपाईंको फोनमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"पात्रो घटनाहरू थप्नुहोस् वा परिमार्जन गर्नुहोस् र मालिकको ज्ञान बिना नै पाहुनाहरूलाई इमेल पठाउनुहोस्"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"यस अनुप्रयोगले तपाईंको ट्याब्लेटमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस अनुप्रयोगले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने सन्देशहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
<string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"यस अनुप्रयोगले तपाईंको TV मा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस अनुप्रयोगले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने सन्देशहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
@@ -1122,6 +1126,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सबै नेटवर्कहरू हेर्न ट्याप गर्नुहोस्"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"जडान गर्नुहोस्"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सबै नेटवर्कहरू"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi स्वतः सक्रिय हुनेछ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"तपाईं कुनै सुरक्षित गरिएको उच्च गुणस्तरीय नेटवर्कको नजिक हुनुभएको अवस्थामा"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"फेरि सक्रिय नगर्नुहोला"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"सञ्जालमा साइन इन गर्नुहोस्"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1209,7 +1216,7 @@
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट लिँदै..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्टलाई साझेदारी गर्ने हो?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्टलाई साझेदारी गर्दै ..."</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"तपाईंका प्रशासकले यस यन्त्रको समस्या निवारण गर्नमा मद्दत गर्नका लागि एउटा बग रिपोर्टको अनुरोध गर्नुभएको छ। अनुप्रयोगहरू र डेटा आदान-प्रदान गर्न पनि सकिन्छ।"</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"तपाईंका प्रशासकले यस यन्त्रको समस्या निवारण गर्नमा मद्दत गर्नका लागि एउटा बग रिपोर्टको अनुरोध गर्नुभएको छ। अनुप्रयोगहरू र डेटा आदान प्रदान गर्न पनि सकिन्छ।"</string>
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझेदारी गर्नुहोस्"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार गर्नुहोस्"</string>
<string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string>
@@ -1806,4 +1813,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"अनुप्रयोगले ब्याकअप तथा पुनर्स्थापनालाई समर्थन नगर्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"अनुप्रयोगमा प्रयोग गरिने हस्ताक्षर नमिल्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/required_apps_managed_device.xml b/core/res/res/values-nl/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-nl/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nl/required_apps_managed_profile.xml b/core/res/res/values-nl/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-nl/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nl/required_apps_managed_user.xml b/core/res/res/values-nl/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-nl/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5ae838e..1d8619c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">" KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Naamloos>"</string>
@@ -835,8 +839,8 @@
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op je tablet. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden.."</string>
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op je tv. De app kan browsergegevens wissen of aanpassen. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op je telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
- <string name="permlab_setAlarm" msgid="1379294556362091814">"een alarm instellen"</string>
- <string name="permdesc_setAlarm" msgid="316392039157473848">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekkerapp. Deze functie wordt door sommige wekkerapps niet geïmplementeerd."</string>
+ <string name="permlab_setAlarm" msgid="1379294556362091814">"een wekker instellen"</string>
+ <string name="permdesc_setAlarm" msgid="316392039157473848">"Hiermee kan de app een wekker instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"voicemail toevoegen"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Hiermee kan de app berichten toevoegen aan de inbox van je voicemail."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"geolocatiemachtigingen voor browser aanpassen"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tik om alle netwerken te bekijken"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Verbinding maken"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netwerken"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wifi wordt automatisch ingeschakeld"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wanneer je in de buurt van een opgeslagen netwerk van hoge kwaliteit bent"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Niet weer inschakelen"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inloggen bij wifi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inloggen bij netwerk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1677,7 +1684,7 @@
<item quantity="one">Gedurende 1 u</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
- <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgend alarm)"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgende wekker)"</string>
<string name="zen_mode_forever" msgid="1916263162129197274">"Totdat je \'Niet storen\' uitschakelt"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat u \'Niet storen\' uitschakelt"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kan snelkoppeling niet herstellen omdat de app geen ondersteuning biedt voor \'Back-up maken en terugzetten\'"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kan snelkoppeling niet herstellen vanwege een niet-overeenkomende app-ondertekening"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kan snelkoppeling niet herstellen"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/required_apps_managed_device.xml b/core/res/res/values-pa/required_apps_managed_device.xml
deleted file mode 100644
index faadc50..0000000
--- a/core/res/res/values-pa/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.download"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pa/required_apps_managed_profile.xml b/core/res/res/values-pa/required_apps_managed_profile.xml
deleted file mode 100644
index 537a80c..0000000
--- a/core/res/res/values-pa/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.download"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pa/required_apps_managed_user.xml b/core/res/res/values-pa/required_apps_managed_user.xml
deleted file mode 100644
index e69bbbc..0000000
--- a/core/res/res/values-pa/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.download"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index b5b6a00..b08b1b2 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ਬਿਨਾਂ ਸਿਰਲੇਖ>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ਸਾਰੇ ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"ਕਨੈਕਟ ਕਰੋ"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ਸਾਰੇ ਨੈੱਟਵਰਕ"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ਵਾਈ‑ਫਾਈ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਚੱਲ ਪਵੇਗਾ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਰੱਖਿਅਤ ਕੀਤੇ ਉੱਚ-ਗੁਣਵੱਤਾ ਵਾਲੇ ਨੈੱਟਵਰਕ ਦੇ ਨੇੜੇ ਹੋਵੋ"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ਵਾਪਸ ਚਾਲੂ ਨਾ ਕਰੋ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ ਕਿਉਂਕਿ ਐਪ \'ਬੈਕਅੱਪ ਅਤੇ ਮੁੜ-ਬਹਾਲੀ\' ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰਦੀ"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ਐਪ ਹਸਤਾਖਰ ਦਾ ਮੇਲ ਨਾ ਹੋਣ ਕਾਰਨ ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ਸ਼ਾਰਟਕੱਟ ਮੁੜ-ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/required_apps_managed_device.xml b/core/res/res/values-pl/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-pl/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pl/required_apps_managed_profile.xml b/core/res/res/values-pl/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-pl/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pl/required_apps_managed_user.xml b/core/res/res/values-pl/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-pl/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 77d706a..108b87b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez nazwy>"</string>
@@ -392,9 +396,9 @@
<string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"Ta aplikacja może dodawać, usuwać i zmieniać wydarzenia z kalendarza na telewizorze. Ta aplikacja może wysyłać wiadomości wyglądające jak utworzone przez właścicieli kalendarza lub zmieniać wydarzenia bez wiedzy ich właścicieli."</string>
<string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"Ta aplikacja może dodawać, usuwać i zmieniać wydarzenia z kalendarza na telefonie. Ta aplikacja może wysyłać wiadomości wyglądające jak utworzone przez właścicieli kalendarza lub zmieniać wydarzenia bez wiedzy ich właścicieli."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-u lub innych źródeł lokalizacji."</string>
- <string name="permlab_accessFineLocation" msgid="251034415460950944">"dostęp do dokładnej lokalizacji (na podstawie GPS-u i sieci)"</string>
- <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"Ta aplikacja może określać Twoją lokalizację na podstawie GPS-u lub sieciowych źródeł lokalizacji, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-a lub innych źródeł lokalizacji."</string>
+ <string name="permlab_accessFineLocation" msgid="251034415460950944">"dostęp do dokładnej lokalizacji (na podstawie GPS-a i sieci)"</string>
+ <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"Ta aplikacja może określać Twoją lokalizację na podstawie GPS-a lub sieciowych źródeł lokalizacji, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
<string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"dostęp do przybliżonej lokalizacji (na podstawie sieci)"</string>
<string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na tablecie, by aplikacja mogła z nich korzystać."</string>
<string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telewizorze, by aplikacja mogła z nich korzystać."</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Kliknij, by zobaczyć wszystkie sieci"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Połącz"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Wszystkie sieci"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi włączy się automatycznie"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Gdy znajdziesz się w pobliżu zapisanej sieci o mocnym sygnale"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nie włączaj ponownie"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Zaloguj się w sieci Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Zaloguj się do sieci"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1260,7 +1267,7 @@
<string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Wyświetlanie nad innymi aplikacjami"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Wyświetlanie aplikacji <xliff:g id="NAME">%s</xliff:g> nad innymi"</string>
<string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacja <xliff:g id="NAME">%s</xliff:g> jest nad innymi"</string>
- <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i ją wyłącz."</string>
+ <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i wyłącz ją."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"WYŁĄCZ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Przygotowuję: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sprawdzanie w poszukiwaniu błędów"</string>
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nie można przywrócić skrótu, bo aplikacja nie obsługuje tworzenia i przywracania kopii zapasowej"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nie można przywrócić skrótu z powodu niezgodności podpisu aplikacji"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nie można przywrócić skrótu"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/required_apps_managed_device.xml b/core/res/res/values-pt-rBR/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-pt-rBR/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rBR/required_apps_managed_profile.xml b/core/res/res/values-pt-rBR/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-pt-rBR/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rBR/required_apps_managed_user.xml b/core/res/res/values-pt-rBR/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-pt-rBR/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index cce4bf0..35cbd28 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sem título>"</string>
@@ -200,9 +204,9 @@
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Sua TV será desligada."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Seu relógio será desligado."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será desligado."</string>
- <string name="shutdown_confirm_question" msgid="2906544768881136183">"Deseja desligar?"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"Quer desligar?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
- <string name="reboot_safemode_confirm" msgid="55293944502784668">"Deseja reiniciar no modo de segurança? Isso desativará todos os apps de terceiros instalados. Eles serão restaurados quando você reiniciar novamente."</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"Quer reiniciar no modo de segurança? Isso desativará todos os apps de terceiros instalados. Eles serão restaurados quando você reiniciar novamente."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
<string name="no_recent_tasks" msgid="8794906658732193473">"Nenhum app recente"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Opções do tablet"</string>
@@ -808,7 +812,7 @@
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Confirmar navegação"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Sair desta página"</string>
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"Permanecer nesta página"</string>
- <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nTem certeza de que deseja sair desta página?"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nTem certeza que quer sair desta página?"</string>
<string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
<string name="double_tap_toast" msgid="4595046515400268881">"Dica: toque duas vezes para aumentar e diminuir o zoom."</string>
<string name="autofill_this_form" msgid="4616758841157816676">"Preench. aut."</string>
@@ -841,7 +845,7 @@
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que o app adicione mensagens a sua caixa de entrada do correio de voz."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifique as permissões de geolocalização de seu navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que o app modifique as permissões de geolocalização do navegador. Apps maliciosos podem usar isso para permitir o envio de informações locais para sites arbitrários."</string>
- <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
+ <string name="save_password_message" msgid="767344687139195790">"Quer que o navegador lembre desta senha?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
<string name="save_password_never" msgid="8274330296785855105">"Nunca"</string>
@@ -1043,7 +1047,7 @@
<string name="force_close" msgid="8346072094521265605">"OK"</string>
<string name="report" msgid="4060218260984795706">"Informar"</string>
<string name="wait" msgid="7147118217226317732">"Aguardar"</string>
- <string name="webpage_unresponsive" msgid="3272758351138122503">"A página não responde.\n\nDeseja fechá-la?"</string>
+ <string name="webpage_unresponsive" msgid="3272758351138122503">"A página não responde.\n\nQuer fechá-la?"</string>
<string name="launch_warning_title" msgid="1547997780506713581">"App redirecionado"</string>
<string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> não está em execução."</string>
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> foi iniciado."</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando você estiver perto de uma rede salva de alta qualidade"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não ativar novamente"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1156,7 +1163,7 @@
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
- <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envia uma grande quantidade de mensagens SMS. Deseja permitir que este app continue enviando mensagens?"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envia uma grande quantidade de mensagens SMS. Quer permitir que este app continue enviando mensagens?"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
<string name="sms_control_no" msgid="625438561395534982">"Negar"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> deseja enviar uma mensagem para <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
@@ -1279,7 +1286,7 @@
<string name="dial_number_using" msgid="5789176425167573586">"Discar número\nusando <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Criar contato \nusando <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"O app a seguir ou outros apps solicitam permissão para acessar sua conta, agora e no futuro."</string>
- <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Deseja permitir essa solicitação?"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Quer permitir essa solicitação?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Solicitação de acesso"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/required_apps_managed_device.xml b/core/res/res/values-pt-rPT/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-pt-rPT/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rPT/required_apps_managed_profile.xml b/core/res/res/values-pt-rPT/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-pt-rPT/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rPT/required_apps_managed_user.xml b/core/res/res/values-pt-rPT/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-pt-rPT/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index dc2d6e4..a9a4a91 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sem nome>"</string>
@@ -951,7 +955,7 @@
<item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> ano</item>
</plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
- <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão em fluxo contínuo neste aparelho."</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão neste aparelho."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
<string name="VideoView_error_button" msgid="2822238215100679592">"OK"</string>
<string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Ligar"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando estiver próximo de uma rede de alta qualidade guardada."</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não reativar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sessão na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Início de sessão na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque a aplicação não é compatível com a funcionalidade de cópia de segurança e restauro."</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido a uma falha de correspondência entre as assinaturas das aplicações."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho."</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/required_apps_managed_device.xml b/core/res/res/values-pt/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-pt/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt/required_apps_managed_profile.xml b/core/res/res/values-pt/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-pt/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt/required_apps_managed_user.xml b/core/res/res/values-pt/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-pt/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index cce4bf0..35cbd28 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Sem título>"</string>
@@ -200,9 +204,9 @@
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Sua TV será desligada."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Seu relógio será desligado."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será desligado."</string>
- <string name="shutdown_confirm_question" msgid="2906544768881136183">"Deseja desligar?"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"Quer desligar?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
- <string name="reboot_safemode_confirm" msgid="55293944502784668">"Deseja reiniciar no modo de segurança? Isso desativará todos os apps de terceiros instalados. Eles serão restaurados quando você reiniciar novamente."</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"Quer reiniciar no modo de segurança? Isso desativará todos os apps de terceiros instalados. Eles serão restaurados quando você reiniciar novamente."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
<string name="no_recent_tasks" msgid="8794906658732193473">"Nenhum app recente"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Opções do tablet"</string>
@@ -808,7 +812,7 @@
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Confirmar navegação"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Sair desta página"</string>
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"Permanecer nesta página"</string>
- <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nTem certeza de que deseja sair desta página?"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nTem certeza que quer sair desta página?"</string>
<string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
<string name="double_tap_toast" msgid="4595046515400268881">"Dica: toque duas vezes para aumentar e diminuir o zoom."</string>
<string name="autofill_this_form" msgid="4616758841157816676">"Preench. aut."</string>
@@ -841,7 +845,7 @@
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que o app adicione mensagens a sua caixa de entrada do correio de voz."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifique as permissões de geolocalização de seu navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que o app modifique as permissões de geolocalização do navegador. Apps maliciosos podem usar isso para permitir o envio de informações locais para sites arbitrários."</string>
- <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
+ <string name="save_password_message" msgid="767344687139195790">"Quer que o navegador lembre desta senha?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
<string name="save_password_never" msgid="8274330296785855105">"Nunca"</string>
@@ -1043,7 +1047,7 @@
<string name="force_close" msgid="8346072094521265605">"OK"</string>
<string name="report" msgid="4060218260984795706">"Informar"</string>
<string name="wait" msgid="7147118217226317732">"Aguardar"</string>
- <string name="webpage_unresponsive" msgid="3272758351138122503">"A página não responde.\n\nDeseja fechá-la?"</string>
+ <string name="webpage_unresponsive" msgid="3272758351138122503">"A página não responde.\n\nQuer fechá-la?"</string>
<string name="launch_warning_title" msgid="1547997780506713581">"App redirecionado"</string>
<string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> não está em execução."</string>
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> foi iniciado."</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando você estiver perto de uma rede salva de alta qualidade"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não ativar novamente"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1156,7 +1163,7 @@
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
- <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envia uma grande quantidade de mensagens SMS. Deseja permitir que este app continue enviando mensagens?"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envia uma grande quantidade de mensagens SMS. Quer permitir que este app continue enviando mensagens?"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
<string name="sms_control_no" msgid="625438561395534982">"Negar"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> deseja enviar uma mensagem para <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
@@ -1279,7 +1286,7 @@
<string name="dial_number_using" msgid="5789176425167573586">"Discar número\nusando <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Criar contato \nusando <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"O app a seguir ou outros apps solicitam permissão para acessar sua conta, agora e no futuro."</string>
- <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Deseja permitir essa solicitação?"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Quer permitir essa solicitação?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Solicitação de acesso"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/required_apps_managed_device.xml b/core/res/res/values-ro/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ro/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ro/required_apps_managed_profile.xml b/core/res/res/values-ro/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ro/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ro/required_apps_managed_user.xml b/core/res/res/values-ro/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ro/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index eece63e..0104894 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TO"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PO"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Fără titlu>"</string>
@@ -1138,6 +1142,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Atingeți pentru a vedea toate rețelele"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectați-vă"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Toate rețelele"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi se va activa automat"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Când vă aflați lângă o rețea salvată, de înaltă calitate"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nu reactivați"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Conectați-vă la rețeaua Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Conectați-vă la rețea"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1835,4 +1842,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nu s-a putut restabili comanda rapidă deoarece aplicația nu acceptă backupul și restabilirea"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nu s-a putut restabili comanda rapidă din cauza nepotrivirii semnăturii aplicației"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nu s-a putut restabili comanda rapidă"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/required_apps_managed_device.xml b/core/res/res/values-ru/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ru/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ru/required_apps_managed_profile.xml b/core/res/res/values-ru/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ru/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ru/required_apps_managed_user.xml b/core/res/res/values-ru/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ru/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 53930c1..460e0c7 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без названия>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Нажмите, чтобы увидеть список сетей"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Подключиться"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Все сети"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi включится автоматически"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Когда вы будете в зоне действия сохраненной сети с хорошим сигналом."</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не включать снова"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Подключение к Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Регистрация в сети"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Не удалось восстановить ярлык: приложение не поддерживает резервное копирование"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Не удалось восстановить ярлык: некорректная подпись приложения"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Не удалось восстановить ярлык"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/required_apps_managed_device.xml b/core/res/res/values-si/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-si/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-si/required_apps_managed_profile.xml b/core/res/res/values-si/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-si/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-si/required_apps_managed_user.xml b/core/res/res/values-si/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-si/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 2a1d635..4188a41 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<නම් යොදා නැත>"</string>
@@ -1118,6 +1122,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"සියලු ජාල බැලීමට තට්ටු කරන්න"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"සම්බන්ධ කරන්න"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"සියලු ජාල"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ස්වයංක්රියව ක්රියාත්මක වනු ඇත"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ඔබ උසස් තත්ත්වයේ සුරැකි ජාලයක් අවට සිටින විට"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"නැවත ක්රියාත්මක නොකරන්න"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ජාලයට පුරනය වන්න"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ජාලයට පුරනය වන්න"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1802,4 +1809,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"යෙදුම උපස්ථ සහ ප්රතිසාධනය සඳහා සහාය නොදක්වන බැවින් කෙටි මග ප්රතිසාධනය කළ නොහැකි විය"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"යෙදුම් අත්සන නොගැළපෙන බැවින් කෙටි මග ප්රතිසාධනය කළ නොහැකි විය"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"කෙටි මග ප්රතිසාධනය කළ නොහැකි විය"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/required_apps_managed_device.xml b/core/res/res/values-sk/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sk/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sk/required_apps_managed_profile.xml b/core/res/res/values-sk/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sk/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sk/required_apps_managed_user.xml b/core/res/res/values-sk/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sk/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index a0de5eb..1fb90ff 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez mena>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Klepnutím zobrazíte všetky siete"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Pripojiť"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Všetky siete"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi sa zapne automaticky"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Keď budete v blízkosti kvalitnej uloženej siete"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Znova nezapínať"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prihlásiť sa do siete Wi‑Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prihlásenie do siete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Odkaz sa nepodarilo obnoviť, pretože aplikácia nepodporuje zálohovanie a obnovu"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Odkaz sa nepodarilo obnoviť pre nesúlad podpisov aplikácie"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Odkaz sa nepodarilo obnoviť"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/required_apps_managed_device.xml b/core/res/res/values-sl/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sl/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sl/required_apps_managed_profile.xml b/core/res/res/values-sl/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sl/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sl/required_apps_managed_user.xml b/core/res/res/values-sl/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sl/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index fb96279..df3c3e7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Brez naslova>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dotaknite se, če si želite ogledati vsa omrežja"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Vzpostavi povezavo"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Vsa omrežja"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Povezava Wi‑Fi se bo samodejno vklopila"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Ko ste v bližini zanesljivega shranjenega omrežja"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne vklopi znova"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavite se v omrežje Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava v omrežje"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Bližnjice ni bilo mogoče obnoviti, ker aplikacija ne podpira varnostnega kopiranja in obnavljanja"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Bližnjice ni bilo mogoče obnoviti zaradi neujemanja podpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Bližnjice ni bilo mogoče obnoviti"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/required_apps_managed_device.xml b/core/res/res/values-sq/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sq/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sq/required_apps_managed_profile.xml b/core/res/res/values-sq/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sq/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sq/required_apps_managed_user.xml b/core/res/res/values-sq/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sq/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 4aee9bc..e6d60d4 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"terabajt"</string>
<string name="petabyteShort" msgid="5637816680144990219">"petabajt"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Pa titull>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Trokit për të parë të gjitha rrjetet"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Lidhu"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Të gjitha rrjetet"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi do të aktivizohet automatikisht"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kur ndodhesh pranë një rrjeti të ruajtur me cilësi të lartë"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Mos e aktivizo përsëri"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Identifikohu në rrjetin Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Identifikohu në rrjet"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nuk mund të restaurohej shkurtorja sepse aplikacioni nuk mbështet rezervimin dhe restaurimin"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nuk mund të restaurohej shkurtorja për shkak të mospërputhjes së nënshkrimit të aplikacionit"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nuk mund të restaurohej shkurtorja"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/required_apps_managed_device.xml b/core/res/res/values-sr/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sr/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sr/required_apps_managed_profile.xml b/core/res/res/values-sr/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sr/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sr/required_apps_managed_user.xml b/core/res/res/values-sr/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sr/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 146f8b3..275db37 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без наслова>"</string>
@@ -1138,6 +1142,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Додирните да бисте видели све мреже"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Повежи"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Све мреже"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ће се аутоматски укључити"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Када сте у близини сачуване мреже високог квалитета"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не укључуј поново"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Пријављивање на Wi-Fi мрежу"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Пријавите се на мрежу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1835,4 +1842,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Враћање пречице није успело јер апликација не подржава прављење резервне копије и враћање"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Враћање пречице није успело јер се потписи апликација не подударају"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Враћање пречице није успело"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/required_apps_managed_device.xml b/core/res/res/values-sv/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sv/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sv/required_apps_managed_profile.xml b/core/res/res/values-sv/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sv/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sv/required_apps_managed_user.xml b/core/res/res/values-sv/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sv/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2705326..1633e43 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Okänd>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tryck för att visa alla nätverk"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Anslut"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alla nätverk"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi aktiveras automatiskt"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"När du är i närheten av ett sparat nätverk av hög kvalitet"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Återaktivera inte"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logga in på ett Wi-Fi-nätverk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1198,7 +1205,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"Ett tillbehör med analog ljudutgång hittades"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Den anslutna enheten är inte kompatibel med mobilen. Tryck här om du vill veta mer."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"Tryck om du vill inaktivera USB-felsökning."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Tryck för att inaktivera USB-felsökning."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Välj för att inaktivera USB-felsökning."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Det gick inte att återställa genvägen eftersom appen inte har stöd för säkerhetskopiering och återställning"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Det gick inte att återställa genvägen eftersom appens signatur inte stämmer"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Det gick inte att återställa genvägen"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/required_apps_managed_device.xml b/core/res/res/values-sw/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-sw/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sw/required_apps_managed_profile.xml b/core/res/res/values-sw/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-sw/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sw/required_apps_managed_user.xml b/core/res/res/values-sw/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-sw/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a8ab410..b98a5c7 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Haina jina>"</string>
@@ -1114,6 +1118,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Gusa ili uone mitandao yote"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Unganisha"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Mitandao Yote"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi itawashwa kiotomatiki"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Unapokuwa karibu na mtandao uliohifadhiwa wenye ubora wa juu"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Usiwashe tena"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Ingia kwa mtandao wa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ingia katika mtandao"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1730,7 +1737,7 @@
<string name="work_mode_turn_on" msgid="2062544985670564875">"Washa"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Una ujumbe mpya"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Fungua programu ya SMS ili uweze kuangalia"</string>
- <string name="user_encrypted_title" msgid="9054897468831672082">"Huenda baadhi ya utendaji ukawa vikwazo"</string>
+ <string name="user_encrypted_title" msgid="9054897468831672082">"Huenda baadhi ya vipengele havifanyi kazi"</string>
<string name="user_encrypted_message" msgid="4923292604515744267">"Gusa ili ufungue"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Data ya mtumiaji imefungwa"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Wasifu wa kazini umefungwa"</string>
@@ -1798,4 +1805,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Imeshindwa kurejesha njia ya mkato kwa sababu programu haitumii kipengele cha hifadhi rudufu na kurejesha upya"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Imeshindwa kurejesha njia ya mkato kwa sababu ufunguo wako wa kuambatisha cheti kwenye programu haulingani"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Imeshindwa kurejesha njia ya mkato"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/required_apps_managed_device.xml b/core/res/res/values-ta/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ta/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ta/required_apps_managed_profile.xml b/core/res/res/values-ta/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ta/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ta/required_apps_managed_user.xml b/core/res/res/values-ta/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ta/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c517223..6014de4 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"பை."</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"கி.பை."</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"மெ.பை."</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ஜி.பை."</string>
+ <string name="terabyteShort" msgid="231613018159186962">"டெ.பை."</string>
<string name="petabyteShort" msgid="5637816680144990219">"பெ.பை."</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<பெயரிடப்படாதது>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"எல்லா நெட்வொர்க்குகளையும் பார்க்க, தட்டவும்"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"இணை"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"எல்லா நெட்வொர்க்குகளும்"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"வைஃபை தானாக ஆன் ஆகும்"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"சேமித்த, உயர்தர நெட்வொர்க்கிற்கு அருகில் இருக்கும்போது"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"மீண்டும் ஆன் செய்யாதே"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"வைஃபை நெட்வொர்க்கில் உள்நுழையவும்"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"நெட்வொர்க்கில் உள்நுழையவும்"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"காப்புப் பிரதி மற்றும் மீட்டமைவைப் பயன்பாடு ஆதரிக்காத காரணத்தால், ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"பயன்பாட்டுச் சான்றுகள் பொருந்தாத காரணத்தினால், ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"ஷார்ட்கட்டை மீட்டமைக்க முடியவில்லை"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/required_apps_managed_device.xml b/core/res/res/values-te/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-te/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-te/required_apps_managed_profile.xml b/core/res/res/values-te/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-te/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-te/required_apps_managed_user.xml b/core/res/res/values-te/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-te/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index fd103bc..a04c529 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<శీర్షిక లేనిది>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"అన్ని నెట్వర్క్లు చూడటానికి నొక్కండి"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"కనెక్ట్ చేయి"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"అన్ని నెట్వర్క్లు"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi స్వయంచాలకంగా ఆన్ అవుతుంది"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"మీరు అధిక నాణ్యత గల సేవ్ చేసిన నెట్వర్క్కు సమీపంగా ఉన్నప్పుడు"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"తిరిగి ఆన్ చేయవద్దు"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"బ్యాకప్ మరియు పునరుద్ధరణకు యాప్ మద్దతు ఇవ్వని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"యాప్ సంతకం సరిపోలని కారణంగా సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"సత్వరమార్గాన్ని పునరుద్ధరించడం సాధ్యపడలేదు"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/required_apps_managed_device.xml b/core/res/res/values-th/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-th/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-th/required_apps_managed_profile.xml b/core/res/res/values-th/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-th/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-th/required_apps_managed_user.xml b/core/res/res/values-th/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-th/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 2515241..d9a504b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<ไม่มีชื่อ>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"แตะเพื่อดูเครือข่ายทั้งหมด"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"เชื่อมต่อ"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"เครือข่ายทั้งหมด"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi จะเปิดโดยอัตโนมัติ"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"เมื่อคุณอยู่ใกล้เครือข่ายคุณภาพสูงที่บันทึกไว้"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ไม่ต้องเปิดอีกครั้ง"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ลงชื่อเข้าใช้เครือข่าย"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"คืนค่าทางลัดไม่ได้เนื่องจากแอปไม่รองรับการสำรองข้อมูลและคืนค่า"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"คืนค่าทางลัดไม่ได้เนื่องจากการลงนามแอปไม่ตรงกัน"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"คืนค่าทางลัดไม่ได้"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/required_apps_managed_device.xml b/core/res/res/values-tl/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-tl/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tl/required_apps_managed_profile.xml b/core/res/res/values-tl/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-tl/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tl/required_apps_managed_user.xml b/core/res/res/values-tl/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-tl/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index d30267b..98e169e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Walang pamagat>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"I-tap upang makita ang lahat ng network"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Kumonekta"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Lahat ng Network"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Awtomatikong mag-o-on ang Wi‑Fi"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kapag malapit ka sa naka-save na network na mataas ang kalidad"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Huwag i-on muli"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Mag-sign in sa Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Mag-sign in sa network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Hindi ma-restore ang shortcut dahil hindi sinusuportahan ng app ang pag-back up at pag-restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Hindi ma-restore ang shortcut dahil hindi magkatugma ang signature ng app"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Hindi ma-restore ang shortcut"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/required_apps_managed_device.xml b/core/res/res/values-tr/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-tr/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tr/required_apps_managed_profile.xml b/core/res/res/values-tr/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-tr/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tr/required_apps_managed_user.xml b/core/res/res/values-tr/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-tr/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e6646c4..e2b1cb3 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Adsız>"</string>
@@ -270,7 +274,7 @@
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"takviminize erişme"</string>
<string name="permgrouprequest_calendar" msgid="6704529828699071445">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının takviminize erişmesine izin verin"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
- <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS iletileri gönderme ve görüntüleme"</string>
+ <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS mesajları gönderme ve görüntüleme"</string>
<string name="permgrouprequest_sms" msgid="605618939583628306">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının SMS mesajları göndermesine ve gelen mesajları görüntülemesine izin verin"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Depolama"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"cihazınızdaki fotoğraflara, medyaya ve dosyalara erişme"</string>
@@ -282,8 +286,8 @@
<string name="permgroupdesc_camera" msgid="3250611594678347720">"fotoğraf çekme ve video kaydetme"</string>
<string name="permgrouprequest_camera" msgid="810824326507258410">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının resim çekmesine ve video kaydı yapmasına izin verin"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Telefon"</string>
- <string name="permgroupdesc_phone" msgid="6234224354060641055">"telefon aramaları yapma ve çağrıları yönetme"</string>
- <string name="permgrouprequest_phone" msgid="7084161459732093690">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının telefon etmesine ve gelen çağrıları yönetmesine izin verin"</string>
+ <string name="permgroupdesc_phone" msgid="6234224354060641055">"telefon çağrıları yapma ve yönetme"</string>
+ <string name="permgrouprequest_phone" msgid="7084161459732093690">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasına telefon çağrıları yapma ve yönetme izni verin"</string>
<string name="permgrouplab_sensors" msgid="416037179223226722">"Vücut Sensörleri"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"hayati belirtilerinizle ilgili sensör verilerine erişme"</string>
<string name="permgrouprequest_sensors" msgid="8631146669524259656">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının hayati belirtilerinizle ilgili sensör verilerine erişmesine izin verin"</string>
@@ -321,7 +325,7 @@
<string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abone olunan yayınları okuma"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Uygulamaya, o anda senkronize olan özet akışları ile ilgili bilgi alma izni verir."</string>
- <string name="permlab_sendSms" msgid="7544599214260982981">"SMS iletileri gönderme ve görüntüleme"</string>
+ <string name="permlab_sendSms" msgid="7544599214260982981">"SMS mesajları gönderme ve görüntüleme"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"Uygulamaya SMS iletisi gönderme izni verir. Bu durum beklenmeyen ödemelere neden olabilir. Kötü amaçlı uygulamalar onayınız olmadan iletiler göndererek sizi zarara uğratabilir."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"kısa mesajlarımı (SMS veya MMS) oku"</string>
<string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"Bu uygulama, tabletinizde kayıtlı tüm SMS mesajlarını (kısa mesajları) okuyabilir."</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tüm ağları görmek için dokunun"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Bağlan"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tüm Ağlar"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Kablosuz özelliği otomatik olarak açılacak"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Daha önce kaydedilmiş yüksek kaliteli bir ağın yakınında olduğunuzda"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Tekrar açılmasın"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kablosuz ağda oturum açın"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ağda oturum açın"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Uygulama, yedekleme ve geri yüklemeyi desteklemediğinden kısayol geri yüklenemedi"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Uygulama imzası eşleşmediğinden kısayol geri yüklenemedi"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kısayol geri yüklenemedi"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/required_apps_managed_device.xml b/core/res/res/values-uk/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-uk/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uk/required_apps_managed_profile.xml b/core/res/res/values-uk/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-uk/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uk/required_apps_managed_user.xml b/core/res/res/values-uk/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-uk/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index bfbe902..788444e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"б"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Без назви>"</string>
@@ -1160,6 +1164,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Торкніться, щоб побачити всі мережі"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Під’єднатися"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Усі мережі"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi вмикатиметься автоматично"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Коли ви поблизу збереженої мережі високої якості"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не вмикати знову"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Вхід у мережу Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Вхід у мережу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1870,4 +1877,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Не вдалося відновити ярлик, оскільки додаток не підтримує резервне копіювання та відновлення"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Не вдалося відновити ярлик, оскільки підписи додатків не збігаються"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Не вдалося відновити ярлик"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/required_apps_managed_device.xml b/core/res/res/values-ur/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-ur/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ur/required_apps_managed_profile.xml b/core/res/res/values-ur/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-ur/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ur/required_apps_managed_user.xml b/core/res/res/values-ur/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-ur/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 2771432..38313d6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"بائٹس"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">">بلا عنوان<"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"تمام نیٹ ورکس دیکھنے کیلئے تھپتھپائيں"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"منسلک کریں"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"تمام نیٹ ورکس"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi از خود آن ہو جائے گا"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"جب آپ اعلی معیار کے محفوظ کردہ نیٹ ورک کے قریب ہوں"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"دوبارہ آن نہ کریں"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"نیٹ ورک میں سائن ان کریں"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"شارٹ کٹ کو بحال نہیں کیا جا سکا، کیونکہ ایپ بیک اپ اور بحالی کو سپورٹ نہیں کرتی ہے"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"ایپ دستخط غیر مماثل ہونے کی وجہ سے شارٹ کٹ کو بحال نہیں کیا جا سکا"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"شارٹ کٹ کو بحال نہیں کیا جا سکا"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/required_apps_managed_device.xml b/core/res/res/values-uz/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-uz/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uz/required_apps_managed_profile.xml b/core/res/res/values-uz/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-uz/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uz/required_apps_managed_user.xml b/core/res/res/values-uz/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-uz/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index c488473..92ec354 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Nomsiz>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Barcha tarmoqlarni ko‘rish uchun bosing"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Ulanish"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Barcha tarmoqlar"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi avtomatik ravishda yoqiladi"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Saqlangan tarmoqlar ichidan signali yaxshisi hududida ekaningizda"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Qayta yoqilmasin"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi tarmoqqa kirish"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Tarmoqqa kirish"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1801,4 +1808,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ilovada zaxiralash va tiklash ishlamagani uchun yorliq tiklanmadi"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ilova imzosi mos kelmagani uchun yorliq tiklanmadi"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Yorliq tiklanmadi"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/required_apps_managed_device.xml b/core/res/res/values-vi/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-vi/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-vi/required_apps_managed_profile.xml b/core/res/res/values-vi/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-vi/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-vi/required_apps_managed_user.xml b/core/res/res/values-vi/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-vi/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 5f72834..f5a1972 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Không có tiêu đề>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Nhấn để xem tất cả các mạng"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Kết nối"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tất cả các mạng"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi sẽ tự động bật"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Khi bạn ở gần mạng đã lưu chất lượng cao"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Không bật lại"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Đăng nhập vào mạng Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Đăng nhập vào mạng"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Không thể khôi phục lối tắt do ứng dụng không hỗ trợ sao lưu và khôi phục"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Không thể khôi phục lối tắt do không khớp chữ ký ứng dụng"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Không thể khôi phục lối tắt"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/required_apps_managed_device.xml b/core/res/res/values-zh-rCN/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-zh-rCN/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rCN/required_apps_managed_profile.xml b/core/res/res/values-zh-rCN/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-zh-rCN/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rCN/required_apps_managed_user.xml b/core/res/res/values-zh-rCN/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-zh-rCN/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 028c082..70b299e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"点按即可查看所有网络"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"连接"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有网络"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WLAN 将自动开启"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"当您位于已保存的高品质网络信号范围内时"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"不要重新开启"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登录到WLAN网络"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登录到网络"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"无法恢复快捷方式,因为应用不支持备份和恢复功能"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"无法恢复快捷方式,因为应用签名不相符"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"无法恢复快捷方式"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/required_apps_managed_device.xml b/core/res/res/values-zh-rHK/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-zh-rHK/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rHK/required_apps_managed_profile.xml b/core/res/res/values-zh-rHK/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-zh-rHK/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rHK/required_apps_managed_user.xml b/core/res/res/values-zh-rHK/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-zh-rHK/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2da0d4a..3dad724 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"輕按即可查看所有網絡"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"連線"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有網絡"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi 將會自動開啟"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"當您位於已儲存的高品質網絡信號範圍內時"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"不要重新開啟"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網絡"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網絡"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"由於應用程式不支援備份和還原功能,因此無法還原捷徑"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"由於應用程式簽署不相符,因此無法還原捷徑"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"無法還原捷徑"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/required_apps_managed_device.xml b/core/res/res/values-zh-rTW/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-zh-rTW/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rTW/required_apps_managed_profile.xml b/core/res/res/values-zh-rTW/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-zh-rTW/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rTW/required_apps_managed_user.xml b/core/res/res/values-zh-rTW/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-zh-rTW/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4f2492f..d3ad7b0 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"位元組"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"KB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"輕觸即可查看所有網路"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"連線"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有網路"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi 將自動開啟"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"當你位於已儲存的高品質網路範圍內時"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"不要重新開啟"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網路"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網路"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"應用程式不支援備份與還原功能,因此無法還原捷徑"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"應用程式簽署不相符,因此無法還原捷徑"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"無法還原捷徑"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/required_apps_managed_device.xml b/core/res/res/values-zu/required_apps_managed_device.xml
deleted file mode 100644
index 9044fcc..0000000
--- a/core/res/res/values-zu/required_apps_managed_device.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_device">
- <item msgid="1104492179978792509">"com.android.settings"</item>
- <item msgid="7004798084799227194">"com.android.contacts"</item>
- <item msgid="5782220690863647256">"com.android.dialer"</item>
- <item msgid="5746338511138092673">"com.android.stk"</item>
- <item msgid="1712599182168590664">"com.android.providers.downloads"</item>
- <item msgid="2858239953396384085">"com.android.providers.downloads.ui"</item>
- <item msgid="3892021562839042708">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zu/required_apps_managed_profile.xml b/core/res/res/values-zu/required_apps_managed_profile.xml
deleted file mode 100644
index 4296b0d..0000000
--- a/core/res/res/values-zu/required_apps_managed_profile.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_profile">
- <item msgid="1457364287544474838">"com.android.contacts"</item>
- <item msgid="4633145750237794002">"com.android.settings"</item>
- <item msgid="6518205098643077579">"com.android.providers.downloads"</item>
- <item msgid="9003577256117829525">"com.android.providers.downloads.ui"</item>
- <item msgid="6106837921940099371">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zu/required_apps_managed_user.xml b/core/res/res/values-zu/required_apps_managed_user.xml
deleted file mode 100644
index 1a7ade9..0000000
--- a/core/res/res/values-zu/required_apps_managed_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string-array name="required_apps_managed_user">
- <item msgid="4823915868435007499">"com.android.settings"</item>
- <item msgid="2250259015310893915">"com.android.contacts"</item>
- <item msgid="7166574999426592423">"com.android.dialer"</item>
- <item msgid="7306937186458176744">"com.android.stk"</item>
- <item msgid="7415441588151512455">"com.android.providers.downloads"</item>
- <item msgid="2277950048461066377">"com.android.providers.downloads.ui"</item>
- <item msgid="8640522622655589373">"com.android.documentsui"</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 2977a85..e91e382 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -21,6 +21,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"B"</string>
+ <string name="kilobyteShort" msgid="7542884022844556968">"kB"</string>
+ <string name="megabyteShort" msgid="6355851576770428922">"MB"</string>
+ <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
+ <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Akunasihloko>"</string>
@@ -1116,6 +1120,9 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Thepha ukuze ubone onke amanethiwekhi"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Xhuma"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Onke amanethiwekhi"</string>
+ <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"I-Wi-Fi izovuleka ngokuzenzakalela"</string>
+ <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Uma useduze kwenethiwekhi yekhwalithi ephezulu elondoloziwe"</string>
+ <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ungaphindi uvule"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ngena ngemvume kunethiwekhi"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1800,4 +1807,6 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ayikwazanga ukubuyisa isinqamuleli ngoba uhlelo lokusebenza alusekeli isipele nokubuyisa"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ayikwazanga ukubuyisa isinqamuleli ngoba isignisha yohlelo lokusebenza ayifani"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ayikwazanga ukubuyisa isinqamuleli"</string>
+ <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1b3d6ce..ee7c795 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4470,6 +4470,10 @@
<attr name="shadowRadius" format="float" />
<!-- Elegant text height, especially for less compacted complex script text. -->
<attr name="elegantTextHeight" format="boolean" />
+ <!-- Whether to respect the ascent and descent of the fallback fonts that are used in
+ displaying the text. When true, fallback fonts that end up getting used can increase
+ the ascent and descent of the lines that they are used on. -->
+ <attr name="fallbackLineSpacing" format="boolean"/>
<!-- Text letter-spacing. -->
<attr name="letterSpacing" format="float" />
<!-- Font feature settings. -->
@@ -4803,6 +4807,10 @@
<attr name="textAllCaps" />
<!-- Elegant text height, especially for less compacted complex script text. -->
<attr name="elegantTextHeight" />
+ <!-- Whether to respect the ascent and descent of the fallback fonts that are used in
+ displaying the text. When true, fallback fonts that end up getting used can increase
+ the ascent and descent of the lines that they are used on. -->
+ <attr name="fallbackLineSpacing" format="boolean"/>
<!-- Text letter-spacing. -->
<attr name="letterSpacing" />
<!-- Font feature settings. -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index fd78500..a078d8b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -73,7 +73,7 @@
<drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
- <color name="input_method_navigation_guard">#ff000000</color>
+ <color name="decor_view_status_guard">#ff000000</color>
<!-- For date picker widget -->
<drawable name="selected_day_background">#ff0092f4</drawable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fd05bb4..2440e9b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2769,6 +2769,13 @@
some existing device-specific resource overlays. -->
<bool name="config_mainBuiltInDisplayIsRound">@bool/config_windowIsRound</bool>
+ <!-- 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. -->
+ <string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
+
<!-- Ultrasound support for Mic/speaker path -->
<!-- Whether the default microphone audio source supports near-ultrasound frequencies
(range of 18 - 21 kHz). -->
@@ -2784,7 +2791,7 @@
<bool name="config_eap_sim_based_auth_supported">true</bool>
<!-- How long history of previous vibrations should be kept for the dumpsys. -->
- <integer name="config_previousVibrationsDumpLimit">20</integer>
+ <integer name="config_previousVibrationsDumpLimit">50</integer>
<!-- The default vibration strength, must be between 1 and 255 inclusive. -->
<integer name="config_defaultVibrationAmplitude">255</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a659b37..2c824ea0 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -152,11 +152,11 @@
<dimen name="dialog_padding">16dp</dimen>
<!-- The margin on the start of the content view -->
- <dimen name="notification_content_margin_start">24dp</dimen>
+ <dimen name="notification_content_margin_start">16dp</dimen>
<!-- The margin on the end of the content view
Keep in sync with notification_content_plus_picture_margin! -->
- <dimen name="notification_content_margin_end">24dp</dimen>
+ <dimen name="notification_content_margin_end">16dp</dimen>
<!-- The margin on the end of the content view with a picture.
Keep in sync with notification_content_plus_picture_margin! -->
@@ -166,7 +166,7 @@
content end margin.
Keep equal to (notification_content_picture_margin + notification_content_margin_end)!
-->
- <dimen name="notification_content_plus_picture_margin_end">80dp</dimen>
+ <dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
<!-- The additional margin on the sides of the ambient view. -->
<dimen name="notification_extra_margin_ambient">16dp</dimen>
@@ -175,10 +175,10 @@
<dimen name="notification_action_list_height">56dp</dimen>
<!-- height of the content margin to accomodate for the header -->
- <dimen name="notification_content_margin_top">41.5dp</dimen>
+ <dimen name="notification_content_margin_top">46dp</dimen>
<!-- height of the content margin on the bottom -->
- <dimen name="notification_content_margin_bottom">18dp</dimen>
+ <dimen name="notification_content_margin_bottom">20dp</dimen>
<!-- The height of the progress bar. -->
<dimen name="notification_progress_bar_height">15dp</dimen>
@@ -187,19 +187,19 @@
<dimen name="notification_progress_margin_top">8dp</dimen>
<!-- height of the notification header (for icon and package name) -->
- <dimen name="notification_header_height">54dp</dimen>
+ <dimen name="notification_header_height">50dp</dimen>
<!-- The height of the background for a notification header on a group -->
<dimen name="notification_header_background_height">49.5dp</dimen>
<!-- The top padding for the notification header -->
- <dimen name="notification_header_padding_top">14dp</dimen>
+ <dimen name="notification_header_padding_top">16dp</dimen>
<!-- The bottom padding for the notification header -->
- <dimen name="notification_header_padding_bottom">13dp</dimen>
+ <dimen name="notification_header_padding_bottom">16dp</dimen>
<!-- The margin at the bottom of the notification header. -->
- <dimen name="notification_header_margin_bottom">5dp</dimen>
+ <dimen name="notification_header_margin_bottom">0dp</dimen>
<!-- The end margin after the application icon in the notification header -->
<dimen name="notification_header_icon_margin_end">3dp</dimen>
@@ -250,7 +250,7 @@
<dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
<!-- The absolute height for the header in a media notification. -->
- <dimen name="media_notification_header_height">53dp</dimen>
+ <dimen name="media_notification_header_height">@dimen/notification_header_height</dimen>
<!-- The margin of the content to an image-->
<dimen name="notification_content_image_margin_end">8dp</dimen>
@@ -590,7 +590,7 @@
<!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
<dimen name="notification_media_image_max_width">280dp</dimen>
<!-- The size of the right icon -->
- <dimen name="notification_right_icon_size">40dp</dimen>
+ <dimen name="notification_right_icon_size">38dp</dimen>
<!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
<dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen>
@@ -607,7 +607,7 @@
<!-- The size of the right icon image when on low ram -->
<dimen name="notification_right_icon_size_low_ram">40dp</dimen>
- <dimen name="messaging_avatar_size">24dp</dimen>
+ <dimen name="messaging_avatar_size">@dimen/notification_right_icon_size</dimen>
<!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
<dimen name="autofill_dataset_picker_max_size">90%</dimen>
@@ -631,4 +631,8 @@
<!-- Default dialog corner radius -->
<dimen name="dialog_corner_radius">2dp</dimen>
+
+ <!-- Size of thumbnail used in the cross profile apps animation -->
+ <dimen name="cross_profile_apps_thumbnail_size">72dp</dimen>
+
</resources>
diff --git a/core/res/res/values/disallowed_apps_managed_device.xml b/core/res/res/values/disallowed_apps_managed_device.xml
index 8940b15..3fb9ba4 100644
--- a/core/res/res/values/disallowed_apps_managed_device.xml
+++ b/core/res/res/values/disallowed_apps_managed_device.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed device. -->
- <string-array name="disallowed_apps_managed_device">
+ <string-array translatable="false" name="disallowed_apps_managed_device">
</string-array>
</resources>
diff --git a/core/res/res/values/disallowed_apps_managed_profile.xml b/core/res/res/values/disallowed_apps_managed_profile.xml
index e3a513f..c3ea8ec 100644
--- a/core/res/res/values/disallowed_apps_managed_profile.xml
+++ b/core/res/res/values/disallowed_apps_managed_profile.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed profile. -->
- <string-array name="disallowed_apps_managed_profile">
+ <string-array translatable="false" name="disallowed_apps_managed_profile">
</string-array>
</resources>
diff --git a/core/res/res/values/disallowed_apps_managed_user.xml b/core/res/res/values/disallowed_apps_managed_user.xml
index b7b645d..e5b29afe 100644
--- a/core/res/res/values/disallowed_apps_managed_user.xml
+++ b/core/res/res/values/disallowed_apps_managed_user.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed user. -->
- <string-array name="disallowed_apps_managed_user">
+ <string-array translatable="false" name="disallowed_apps_managed_user">
</string-array>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8540ff1..6ec88dc 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2860,6 +2860,7 @@
<public name="isVrOnly"/>
<public name="widgetFeatures" />
<public name="appComponentFactory" />
+ <public name="fallbackLineSpacing" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml
index 0ac706f..40db9df 100644
--- a/core/res/res/values/required_apps_managed_device.xml
+++ b/core/res/res/values/required_apps_managed_device.xml
@@ -19,7 +19,7 @@
<resources>
<!-- A list of apps to be retained on the managed device.
Takes precedence over the disallowed apps lists. -->
- <string-array name="required_apps_managed_device">
+ <string-array translatable="false" name="required_apps_managed_device">
<item>com.android.settings</item>
<item>com.android.contacts</item>
<item>com.android.dialer</item>
diff --git a/core/res/res/values/required_apps_managed_profile.xml b/core/res/res/values/required_apps_managed_profile.xml
index a0b8492..c6b37e8 100644
--- a/core/res/res/values/required_apps_managed_profile.xml
+++ b/core/res/res/values/required_apps_managed_profile.xml
@@ -19,7 +19,7 @@
<resources>
<!-- A list of apps to be retained in the managed profile.
Takes precedence over the disallowed apps lists. -->
- <string-array name="required_apps_managed_profile">
+ <string-array translatable="false" name="required_apps_managed_profile">
<item>com.android.contacts</item>
<item>com.android.settings</item>
<item>com.android.providers.downloads</item>
diff --git a/core/res/res/values/required_apps_managed_user.xml b/core/res/res/values/required_apps_managed_user.xml
index e8fdb21..8800e535 100644
--- a/core/res/res/values/required_apps_managed_user.xml
+++ b/core/res/res/values/required_apps_managed_user.xml
@@ -19,7 +19,7 @@
<resources>
<!-- A list of apps to be retained on the managed user.
Takes precedence over the disallowed apps lists. -->
- <string-array name="required_apps_managed_user">
+ <string-array translatable="false" name="required_apps_managed_user">
<item>com.android.settings</item>
<item>com.android.contacts</item>
<item>com.android.dialer</item>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c54f799..0618a82 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4785,6 +4785,11 @@
-->
<string name="shortcut_restore_unknown_issue">Couldn\u2019t restore shortcut</string>
+ <!--
+ A toast message shown when an app shortcut is disabled for an unknown rason.
+ -->
+ <string name="shortcut_disabled_reason_unknown">Shortcut is disabled</string>
+
<!--Battery saver warning. STOPSHIP: Remove it eventually. -->
<string name="battery_saver_warning" translatable="false">\"Extreme\" battery saver activated.\n\nSee the details at: go/extreme-battery-saver\n\nEBS aggressively throttles background apps and changes screen-off behavior.\n</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index def650a..fa3cf2f 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -502,20 +502,17 @@
<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
<style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
- <item name="layout_width">match_parent</item>
+ <item name="layout_width">wrap_content</item>
<item name="layout_height">wrap_content</item>
<item name="ellipsize">end</item>
<item name="textAppearance">@style/TextAppearance.Material.Notification</item>
- <item name="background">@drawable/messaging_message_background</item>
</style>
<style name="Widget.Material.Notification.MessagingName" parent="Widget.Material.Light.TextView">
<item name="layout_width">wrap_content</item>
<item name="layout_height">wrap_content</item>
<item name="ellipsize">end</item>
- <item name="textAppearance">@style/TextAppearance.Material.Notification</item>
- <item name="textColor">@color/notification_primary_text_color_light</item>
- <item name="textSize">12sp</item>
+ <item name="textAppearance">@style/TextAppearance.Material.Notification.Title</item>
</style>
<!-- Widget Styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4343ba0..ac3d402 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1578,8 +1578,10 @@
<java-symbol type="anim" name="voice_activity_close_enter" />
<java-symbol type="anim" name="voice_activity_open_exit" />
<java-symbol type="anim" name="voice_activity_open_enter" />
- <java-symbol type="anim" name="activity_open_exit" />
- <java-symbol type="anim" name="activity_open_enter" />
+ <java-symbol type="anim" name="task_open_exit" />
+ <java-symbol type="anim" name="task_open_enter" />
+ <java-symbol type="anim" name="cross_profile_apps_thumbnail_enter" />
+ <java-symbol type="anim" name="task_open_enter_cross_profile_apps" />
<java-symbol type="array" name="config_autoRotationTiltTolerance" />
<java-symbol type="array" name="config_keyboardTapVibePattern" />
@@ -1726,6 +1728,7 @@
<java-symbol type="style" name="Theme.ExpandedMenu" />
<java-symbol type="string" name="forward_intent_to_owner" />
<java-symbol type="string" name="forward_intent_to_work" />
+ <java-symbol type="dimen" name="cross_profile_apps_thumbnail_size" />
<!-- From services -->
<java-symbol type="anim" name="screen_rotate_0_enter" />
@@ -1812,7 +1815,7 @@
<java-symbol type="bool" name="config_wimaxEnabled" />
<java-symbol type="bool" name="show_ongoing_ime_switcher" />
<java-symbol type="color" name="config_defaultNotificationColor" />
- <java-symbol type="color" name="input_method_navigation_guard" />
+ <java-symbol type="color" name="decor_view_status_guard" />
<java-symbol type="drawable" name="ic_notification_ime_default" />
<java-symbol type="drawable" name="ic_menu_refresh" />
<java-symbol type="drawable" name="ic_settings" />
@@ -2605,10 +2608,12 @@
<java-symbol type="string" name="notification_hidden_text" />
<java-symbol type="id" name="app_name_text" />
<java-symbol type="id" name="header_text" />
+ <java-symbol type="id" name="header_text_secondary" />
<java-symbol type="id" name="expand_button" />
<java-symbol type="id" name="notification_header" />
<java-symbol type="id" name="time_divider" />
<java-symbol type="id" name="header_text_divider" />
+ <java-symbol type="id" name="header_text_secondary_divider" />
<java-symbol type="id" name="text_line_1" />
<java-symbol type="drawable" name="ic_expand_notification" />
<java-symbol type="drawable" name="ic_collapse_notification" />
@@ -3195,9 +3200,12 @@
<java-symbol type="string" name="battery_saver_warning_title" />
<java-symbol type="string" name="global_action_logout" />
+ <java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
<java-symbol type="drawable" name="ic_logout" />
<java-symbol type="array" name="config_autoBrightnessDisplayValuesNits" />
<java-symbol type="array" name="config_screenBrightnessBacklight" />
<java-symbol type="array" name="config_screenBrightnessNits" />
+
+ <java-symbol type="string" name="shortcut_disabled_reason_unknown" />
</resources>
diff --git a/core/res/res/values/vendor_disallowed_apps_managed_device.xml b/core/res/res/values/vendor_disallowed_apps_managed_device.xml
index c826d27..493cd60 100644
--- a/core/res/res/values/vendor_disallowed_apps_managed_device.xml
+++ b/core/res/res/values/vendor_disallowed_apps_managed_device.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed device by a particular vendor. -->
- <string-array name="vendor_disallowed_apps_managed_device">
+ <string-array translatable="false" name="vendor_disallowed_apps_managed_device">
</string-array>
</resources>
diff --git a/core/res/res/values/vendor_disallowed_apps_managed_profile.xml b/core/res/res/values/vendor_disallowed_apps_managed_profile.xml
index 5fcb2778..84cab5f 100644
--- a/core/res/res/values/vendor_disallowed_apps_managed_profile.xml
+++ b/core/res/res/values/vendor_disallowed_apps_managed_profile.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed profile by a particular vendor. -->
- <string-array name="vendor_disallowed_apps_managed_profile">
+ <string-array translatable="false" name="vendor_disallowed_apps_managed_profile">
</string-array>
</resources>
diff --git a/core/res/res/values/vendor_disallowed_apps_managed_user.xml b/core/res/res/values/vendor_disallowed_apps_managed_user.xml
index 3355d77..975bb5d 100644
--- a/core/res/res/values/vendor_disallowed_apps_managed_user.xml
+++ b/core/res/res/values/vendor_disallowed_apps_managed_user.xml
@@ -18,6 +18,6 @@
-->
<resources>
<!-- A list of apps to be removed from the managed user by a particular vendor. -->
- <string-array name="vendor_disallowed_apps_managed_user">
+ <string-array translatable="false" name="vendor_disallowed_apps_managed_user">
</string-array>
</resources>
diff --git a/core/res/res/values/vendor_required_apps_managed_device.xml b/core/res/res/values/vendor_required_apps_managed_device.xml
index e684e22..1ef48db 100644
--- a/core/res/res/values/vendor_required_apps_managed_device.xml
+++ b/core/res/res/values/vendor_required_apps_managed_device.xml
@@ -19,6 +19,6 @@
<resources>
<!-- A list of apps to be retained on the managed device by a particular vendor.
Takes precedence over the disallowed apps lists. -->
- <string-array name="vendor_required_apps_managed_device">
+ <string-array translatable="false" name="vendor_required_apps_managed_device">
</string-array>
</resources>
diff --git a/core/res/res/values/vendor_required_apps_managed_profile.xml b/core/res/res/values/vendor_required_apps_managed_profile.xml
index 4a3edf8..49cfa8b 100644
--- a/core/res/res/values/vendor_required_apps_managed_profile.xml
+++ b/core/res/res/values/vendor_required_apps_managed_profile.xml
@@ -19,6 +19,6 @@
<resources>
<!-- A list of apps to be retained in the managed profile by a particular vendor.
Takes precedence over the disallowed apps lists. -->
- <string-array name="vendor_required_apps_managed_profile">
+ <string-array translatable="false" name="vendor_required_apps_managed_profile">
</string-array>
</resources>
diff --git a/core/res/res/values/vendor_required_apps_managed_user.xml b/core/res/res/values/vendor_required_apps_managed_user.xml
index 71dbd62..bad7803 100644
--- a/core/res/res/values/vendor_required_apps_managed_user.xml
+++ b/core/res/res/values/vendor_required_apps_managed_user.xml
@@ -19,6 +19,6 @@
<resources>
<!-- A list of apps to be retained on the managed user by a particular vendor.
Takes precedence over the disallowed apps lists. -->
- <string-array name="vendor_required_apps_managed_user">
+ <string-array translatable="false" name="vendor_required_apps_managed_user">
</string-array>
</resources>
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
index a8d5164..896fd15 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
@@ -149,6 +149,10 @@
mRadioTuner = mRadioManager.openTuner(mModule.getId(),
mFmBandConfig, withAudio, mCallback, null);
+ if (!withAudio) {
+ // non-audio sessions might not be supported - if so, then skip the test
+ assumeNotNull(mRadioTuner);
+ }
assertNotNull(mRadioTuner);
verify(mCallback, timeout(kConfigCallbackTimeoutMs)).onConfigurationChanged(any());
resetCallback();
@@ -207,20 +211,8 @@
public void testSetBadConfiguration() throws Throwable {
openTuner();
- // set bad config
- Constructor<RadioManager.AmBandConfig> configConstr =
- RadioManager.AmBandConfig.class.getDeclaredConstructor(
- int.class, int.class, int.class, int.class, int.class, boolean.class);
- configConstr.setAccessible(true);
- RadioManager.AmBandConfig badConfig = configConstr.newInstance(
- 0 /*region*/, RadioManager.BAND_AM /*type*/,
- 10000 /*lowerLimit*/, 1 /*upperLimit*/, 100 /*spacing*/, false /*stereo*/);
- int ret = mRadioTuner.setConfiguration(badConfig);
- assertEquals(RadioManager.STATUS_BAD_VALUE, ret);
- verify(mCallback, never()).onConfigurationChanged(any());
-
// set null config
- ret = mRadioTuner.setConfiguration(null);
+ int ret = mRadioTuner.setConfiguration(null);
assertEquals(RadioManager.STATUS_BAD_VALUE, ret);
verify(mCallback, never()).onConfigurationChanged(any());
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 7183934..b51c677 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -28,6 +28,7 @@
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.media.session.MediaSession;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.test.InstrumentationRegistry;
@@ -215,9 +216,11 @@
}
@Test
- public void testMessagingStyle_isGroupConversation() {
+ public void messagingStyle_isGroupConversation() {
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
- .setGroupConversation(true);
+ .setGroupConversation(true)
+ .setConversationTitle("test conversation title");
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
@@ -228,6 +231,56 @@
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
+ @Test
+ public void messagingStyle_isGroupConversation_noConversationTitle() {
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(true)
+ .setConversationTitle(null);
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertTrue(messagingStyle.isGroupConversation());
+ assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
+ @Test
+ public void messagingStyle_isGroupConversation_withConversationTitle_legacy() {
+ // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(false)
+ .setConversationTitle("test conversation title");
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertTrue(messagingStyle.isGroupConversation());
+ assertFalse(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
+ @Test
+ public void messagingStyle_isGroupConversation_withoutConversationTitle_legacy() {
+ // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(true)
+ .setConversationTitle(null);
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertFalse(messagingStyle.isGroupConversation());
+ assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
private Notification.Builder getMediaNotification() {
MediaSession session = new MediaSession(mContext, "test");
return new Notification.Builder(mContext, "color")
diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
index 1a54bd6..63a5e4c 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
@@ -41,6 +41,8 @@
private static final String ANDROID_TEST_MOCK = "android.test.mock";
+ private static final String OTHER_LIBRARY = "other.library";
+
private Package mPackage;
private static ArrayList<String> arrayList(String... strings) {
@@ -78,6 +80,18 @@
}
@Test
+ public void targeted_at_O_not_empty_usesLibraries() {
+ mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+ mPackage.usesLibraries = arrayList(OTHER_LIBRARY);
+ PackageBackwardCompatibility.modifySharedLibraries(mPackage);
+ // The org.apache.http.legacy jar should be added at the start of the list.
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY),
+ mPackage.usesLibraries);
+ assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
+ }
+
+ @Test
public void targeted_at_O_org_apache_http_legacy_in_usesLibraries() {
mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
mPackage.usesLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index b7a48c7..64fadc0 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -16,6 +16,8 @@
package android.graphics.drawable;
+import static com.google.common.truth.Truth.assertThat;
+
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Region;
@@ -108,6 +110,19 @@
}
@SmallTest
+ public void testScaleDownIfNecessary() throws Exception {
+ final Bitmap bm = Bitmap.createBitmap(4321, 78, Bitmap.Config.ARGB_8888);
+ final Icon ic = Icon.createWithBitmap(bm);
+ ic.scaleDownIfNecessary(40, 20);
+
+ assertThat(bm.getWidth()).isEqualTo(4321);
+ assertThat(bm.getHeight()).isEqualTo(78);
+
+ assertThat(ic.getBitmap().getWidth()).isLessThan(41);
+ assertThat(ic.getBitmap().getHeight()).isLessThan(21);
+ }
+
+ @SmallTest
public void testWithAdaptiveBitmap() throws Exception {
final Bitmap bm1 = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
diff --git a/core/tests/coretests/src/android/os/WorkSourceTest.java b/core/tests/coretests/src/android/os/WorkSourceTest.java
index 90b4575..a427a2f 100644
--- a/core/tests/coretests/src/android/os/WorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceTest.java
@@ -128,6 +128,23 @@
assertFalse(ws3.equals(ws1));
}
+ public void testEquals_workChains_nullEmptyAreEquivalent() {
+ // Construct a WorkSource that has no WorkChains, but whose workChains list
+ // is non-null.
+ WorkSource ws1 = new WorkSource();
+ ws1.add(100);
+ ws1.createWorkChain().addNode(100, null);
+ ws1.getWorkChains().clear();
+
+ WorkSource ws2 = new WorkSource();
+ ws2.add(100);
+
+ assertEquals(ws1, ws2);
+
+ ws2.createWorkChain().addNode(100, null);
+ assertFalse(ws1.equals(ws2));
+ }
+
public void testWorkSourceParcelling() {
WorkSource ws = new WorkSource();
@@ -331,4 +348,24 @@
wc.addNode(200, "tag2");
assertEquals(100, wc.getAttributionUid());
}
+
+ public void testRemove_fromChainedWorkSource() {
+ WorkSource ws1 = new WorkSource();
+ ws1.createWorkChain().addNode(50, "foo");
+ ws1.createWorkChain().addNode(75, "bar");
+ ws1.add(100);
+
+ WorkSource ws2 = new WorkSource();
+ ws2.add(100);
+
+ assertTrue(ws1.remove(ws2));
+ assertEquals(2, ws1.getWorkChains().size());
+ assertEquals(50, ws1.getWorkChains().get(0).getAttributionUid());
+ assertEquals(75, ws1.getWorkChains().get(1).getAttributionUid());
+
+ ws2.createWorkChain().addNode(50, "foo");
+ assertTrue(ws1.remove(ws2));
+ assertEquals(1, ws1.getWorkChains().size());
+ assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid());
+ }
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index fc86500..68789f3 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -112,6 +112,7 @@
Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
+ Settings.Global.BATTERY_STATS_CONSTANTS,
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
@@ -210,6 +211,7 @@
Settings.Global.EUICC_FACTORY_RESET_TIMEOUT_MILLIS,
Settings.Global.FANCY_IME_ANIMATIONS,
Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
+ Settings.Global.FORCED_APP_STANDBY_ENABLED,
Settings.Global.FSTRIM_MANDATORY_INTERVAL,
Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Settings.Global.GLOBAL_HTTP_PROXY_HOST,
@@ -281,6 +283,7 @@
Settings.Global.NETWORK_SCORING_UI_ENABLED,
Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
+ Settings.Global.NETWORK_WATCHLIST_ENABLED,
Settings.Global.NEW_CONTACT_AGGREGATOR,
Settings.Global.NITZ_UPDATE_DIFF,
Settings.Global.NITZ_UPDATE_SPACING,
@@ -452,7 +455,6 @@
Settings.Secure.COMPLETED_CATEGORY_PREFIX,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
Settings.Secure.DEFAULT_INPUT_METHOD,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE,
Settings.Secure.DEVICE_PAIRED,
Settings.Secure.DIALER_DEFAULT_APPLICATION,
Settings.Secure.DISABLED_PRINT_SERVICES,
diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
new file mode 100644
index 0000000..1e3ddf3
--- /dev/null
+++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.service.euicc;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.service.carrier.CarrierIdentifier;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.UiccAccessRule;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EuiccProfileInfoTest {
+ @Test
+ public void testWriteToParcel() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testWriteToParcelNullCarrierId() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testBuilderAndGetters() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertEquals("21430000000000006587", p.getIccid());
+ assertEquals("profile nickname", p.getNickname());
+ assertEquals("profile name", p.getProfileName());
+ assertEquals("service provider", p.getServiceProviderName());
+ assertEquals("325", p.getCarrierIdentifier().getMcc());
+ assertEquals("764", p.getCarrierIdentifier().getMnc());
+ assertEquals("123", p.getCarrierIdentifier().getGid1());
+ assertEquals("45", p.getCarrierIdentifier().getGid2());
+ assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, p.getState());
+ assertEquals(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, p.getProfileClass());
+ assertEquals(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, p.getPolicyRules());
+ assertTrue(p.hasPolicyRules());
+ assertTrue(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE));
+ assertFalse(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE));
+ assertArrayEquals(
+ new UiccAccessRule[] {new UiccAccessRule(new byte[0], null, 0)},
+ p.getUiccAccessRules());
+ }
+
+ @Test
+ public void testBuilder_BasedOnAnotherProfile() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build();
+
+ assertEquals(p, copied);
+ assertEquals(p.hashCode(), copied.hashCode());
+ }
+
+ @Test
+ public void testEqualsHashCode() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertTrue(p.equals(p));
+ assertFalse(p.equals(new Object()));
+
+ EuiccProfileInfo t = null;
+ assertFalse(p.equals(t));
+
+ t = new EuiccProfileInfo.Builder(p).setIccid("21").build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setNickname(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setProfileName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setServiceProviderName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setCarrierIdentifier(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setState(EuiccProfileInfo.PROFILE_STATE_DISABLED).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_TESTING).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setPolicyRules(0).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setUiccAccessRule(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilderBuild_NoIccid() {
+ new EuiccProfileInfo.Builder().build();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBuilderSetOperatorMccMnc_Illegal() {
+ new EuiccProfileInfo.Builder()
+ .setCarrierIdentifier(new CarrierIdentifier(new byte[] {1, 2, 3, 4}, null, null));
+ }
+
+ @Test
+ public void testCreatorNewArray() {
+ EuiccProfileInfo[] profiles = EuiccProfileInfo.CREATOR.newArray(123);
+ assertEquals(123, profiles.length);
+ }
+}
diff --git a/core/tests/coretests/src/android/util/DataUnitTest.java b/core/tests/coretests/src/android/util/DataUnitTest.java
new file mode 100644
index 0000000..4eae8b4
--- /dev/null
+++ b/core/tests/coretests/src/android/util/DataUnitTest.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.util;
+
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+@SmallTest
+public class DataUnitTest extends TestCase {
+ public void testSi() throws Exception {
+ assertEquals(12_000L, DataUnit.KILOBYTES.toBytes(12));
+ assertEquals(12_000_000L, DataUnit.MEGABYTES.toBytes(12));
+ assertEquals(12_000_000_000L, DataUnit.GIGABYTES.toBytes(12));
+ }
+
+ public void testIec() throws Exception {
+ assertEquals(12_288L, DataUnit.KIBIBYTES.toBytes(12));
+ assertEquals(12_582_912L, DataUnit.MEBIBYTES.toBytes(12));
+ assertEquals(12_884_901_888L, DataUnit.GIBIBYTES.toBytes(12));
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java b/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java
new file mode 100644
index 0000000..e9d1d3e
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.text.DynamicLayout;
+import android.text.FontFallbackSetup;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.TextView.BufferType;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Parametrized test for TextView#setFallbackLineSpacing.
+ */
+@MediumTest
+@RunWith(Parameterized.class)
+public class TextViewFallbackLineSpacingTest {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection layouts() {
+ return Arrays.asList(new Object[][] {
+ // name, enabled, BufferType
+ { "Enabled - StaticLayout", true, BufferType.NORMAL},
+ { "Disabled - StaticLayout", false, BufferType.NORMAL},
+ { "Enabled - DynamicLayout", true, BufferType.EDITABLE},
+ { "Disabled - DynamicLayout", false, BufferType.EDITABLE},
+ });
+ }
+
+ @Rule
+ public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
+ TextViewActivity.class);
+
+ private final boolean mEnabled;
+ private final BufferType mBufferType;
+
+ public TextViewFallbackLineSpacingTest(String testName, boolean enabled,
+ BufferType bufferType) {
+ mEnabled = enabled;
+ mBufferType = bufferType;
+ }
+
+ @Test
+ public void testFallbackLineSpacing() {
+ // All glyphs in the fonts are 1em wide.
+ final String[] testFontFiles = {
+ // ascent == 1em, descent == 2em, only supports 'a' and space
+ "ascent1em-descent2em.ttf",
+ // ascent == 3em, descent == 4em, only supports 'b'
+ "ascent3em-descent4em.ttf"
+ };
+ final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ + "<familyset>"
+ + " <family name='sans-serif'>"
+ + " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>"
+ + " </family>"
+ + " <family>"
+ + " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>"
+ + " </family>"
+ + "</familyset>";
+
+ try (FontFallbackSetup setup =
+ new FontFallbackSetup("DynamicLayout", testFontFiles, xml)) {
+ final Activity activity = mActivityRule.getActivity();
+ final TextView textView = new TextView(activity);
+ textView.setTypeface(setup.getTypefaceFor("sans-serif"));
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 100);
+ // This should result in three lines.
+ textView.setText("aaaaa aabaa aaaaa", mBufferType);
+ textView.setPadding(0, 0, 0, 0);
+ textView.setIncludeFontPadding(false);
+ textView.setFallbackLineSpacing(mEnabled);
+
+ final int em = (int) Math.ceil(textView.getPaint().measureText("a"));
+ final int width = 5 * em;
+ final int height = 30 * em; // tall enough to not affect our other measurements
+ textView.measure(
+ View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
+ textView.layout(0, 0, width, height);
+
+ final Layout layout = textView.getLayout();
+ assertNotNull(layout);
+ if (mBufferType == BufferType.NORMAL) {
+ assertTrue(layout instanceof StaticLayout);
+ } else {
+ assertTrue(layout instanceof DynamicLayout);
+ }
+ assertEquals(3, layout.getLineCount());
+
+ assertEquals(-em, layout.getLineAscent(0));
+ assertEquals(2 * em, layout.getLineDescent(0));
+
+ if (mEnabled) {
+ // The second line has a 'b', so it needs more ascent and descent.
+ assertEquals(-3 * em, layout.getLineAscent(1));
+ assertEquals(4 * em, layout.getLineDescent(1));
+ } else {
+ // old behavior
+ assertEquals(-em, layout.getLineAscent(1));
+ assertEquals(2 * em, layout.getLineDescent(1));
+ }
+
+ assertEquals(-em, layout.getLineAscent(2));
+ assertEquals(2 * em, layout.getLineDescent(2));
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 5dec42e..2b5b27b 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -30,12 +30,10 @@
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.text.FontFallbackSetup;
import android.text.GetChars;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
-import android.util.TypedValue;
import android.view.View;
import org.junit.Before;
@@ -251,56 +249,4 @@
}
return builder.toString();
}
-
- @Test
- public void testFallbackLineSpacing() {
- // All glyphs in the fonts are 1em wide.
- final String[] testFontFiles = {
- // ascent == 1em, descent == 2em, only supports 'a' and space
- "ascent1em-descent2em.ttf",
- // ascent == 3em, descent == 4em, only supports 'b'
- "ascent3em-descent4em.ttf"
- };
- final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
- + "<familyset>"
- + " <family name='sans-serif'>"
- + " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>"
- + " </family>"
- + " <family>"
- + " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>"
- + " </family>"
- + "</familyset>";
-
- try (FontFallbackSetup setup =
- new FontFallbackSetup("DynamicLayout", testFontFiles, xml)) {
- mTextView = new TextView(mActivity);
- mTextView.setTypeface(setup.getTypefaceFor("sans-serif"));
- mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 100);
- mTextView.setText("aaaaa aabaa aaaaa"); // This should result in three lines.
- mTextView.setPadding(0, 0, 0, 0);
- mTextView.setIncludeFontPadding(false);
-
- final int em = (int) Math.ceil(mTextView.getPaint().measureText("a"));
- final int width = 5 * em;
- final int height = 30 * em; // tall enough to not affect our other measurements
- mTextView.measure(
- View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
- View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
- mTextView.layout(0, 0, width, height);
-
- final Layout layout = mTextView.getLayout();
- assertNotNull(layout);
- assertEquals(3, layout.getLineCount());
-
- assertEquals(-em, layout.getLineAscent(0));
- assertEquals(2 * em, layout.getLineDescent(0));
-
- // The second line has a 'b', so it needs more ascent and descent.
- assertEquals(-3 * em, layout.getLineAscent(1));
- assertEquals(4 * em, layout.getLineDescent(1));
-
- assertEquals(-em, layout.getLineAscent(2));
- assertEquals(2 * em, layout.getLineDescent(2));
- }
- }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 3794b5f..a8094ea 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -71,7 +71,7 @@
@Test
public void testUpdateProcStateCpuTimes() {
mBatteryStatsImpl.setOnBatteryInternal(true);
- mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+ mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0);
final int[] testUids = {10032, 10048, 10145, 10139};
final int[] testProcStates = {
@@ -98,7 +98,7 @@
}
}
- mBatteryStatsImpl.updateProcStateCpuTimes();
+ mBatteryStatsImpl.updateProcStateCpuTimes(true, false);
verifyNoPendingUids();
for (int i = 0; i < testUids.length; ++i) {
@@ -125,7 +125,7 @@
}
addPendingUids(testUids, testProcStates);
- mBatteryStatsImpl.updateProcStateCpuTimes();
+ mBatteryStatsImpl.updateProcStateCpuTimes(true, false);
verifyNoPendingUids();
for (int i = 0; i < testUids.length; ++i) {
@@ -157,7 +157,7 @@
}
addPendingUids(testUids, testProcStates);
- mBatteryStatsImpl.updateProcStateCpuTimes();
+ mBatteryStatsImpl.updateProcStateCpuTimes(true, true);
verifyNoPendingUids();
for (int i = 0; i < testUids.length; ++i) {
@@ -196,7 +196,7 @@
final long[] isolatedUidCpuTimes = {495784, 398473, 4895, 4905, 30984093};
when(mKernelSingleUidTimeReader.readDeltaMs(childUid)).thenReturn(isolatedUidCpuTimes);
- mBatteryStatsImpl.updateProcStateCpuTimes();
+ mBatteryStatsImpl.updateProcStateCpuTimes(true, true);
verifyNoPendingUids();
for (int i = 0; i < testUids.length; ++i) {
@@ -227,8 +227,8 @@
@Test
public void testCopyFromAllUidsCpuTimes() {
- mBatteryStatsImpl.setOnBatteryInternal(true);
- mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+ mBatteryStatsImpl.setOnBatteryInternal(false);
+ mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0);
final int[] testUids = {10032, 10048, 10145, 10139};
final int[] testProcStates = {
@@ -264,7 +264,7 @@
.thenReturn(expectedCpuTimes[i]);
}
- mBatteryStatsImpl.copyFromAllUidsCpuTimes();
+ mBatteryStatsImpl.copyFromAllUidsCpuTimes(true, false);
verifyNoPendingUids();
for (int i = 0; i < testUids.length; ++i) {
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index e54fe7d..4d34721 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -25,6 +25,8 @@
import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING;
import static android.os.BatteryStats.Uid.UID_PROCESS_TYPES;
+import static com.android.internal.os.BatteryStatsImpl.Constants.KEY_TRACK_CPU_TIMES_BY_PROC_STATE;
+
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -48,15 +50,19 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.SystemClock;
+import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
+import android.text.TextUtils;
import android.util.DebugUtils;
import android.util.Log;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import java.util.Arrays;
@@ -86,6 +92,9 @@
private static final int START_SERVICE_TIMEOUT_MS = 2000;
private static final int START_ISOLATED_SERVICE_TIMEOUT_MS = 2000;
+ private static final int SETTING_UPDATE_TIMEOUT_MS = 2000;
+ private static final int SETTING_UPDATE_CHECK_INTERVAL_MS = 200;
+
private static final int GENERAL_TIMEOUT_MS = 4000;
private static final int GENERAL_INTERVAL_MS = 200;
@@ -97,6 +106,8 @@
private static boolean sCpuFreqTimesAvailable;
private static boolean sPerProcStateTimesAvailable;
+ @Rule public TestName testName = new TestName();
+
@BeforeClass
public static void setupOnce() throws Exception {
sContext = InstrumentationRegistry.getContext();
@@ -123,6 +134,9 @@
@Test
public void testCpuFreqTimes() throws Exception {
if (!sCpuFreqTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -148,6 +162,9 @@
@Test
public void testCpuFreqTimes_screenOff() throws Exception {
if (!sCpuFreqTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -179,6 +196,9 @@
@Test
public void testCpuFreqTimes_isolatedProcess() throws Exception {
if (!sCpuFreqTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -204,6 +224,9 @@
@Test
public void testCpuFreqTimes_stateTop() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -234,6 +257,9 @@
@Test
public void testIsolatedCpuFreqTimes_stateService() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -272,6 +298,9 @@
@Test
public void testCpuFreqTimes_stateTopSleeping() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -302,6 +331,9 @@
@Test
public void testCpuFreqTimes_stateFgService() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -332,6 +364,9 @@
@Test
public void testCpuFreqTimes_stateFg() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -362,6 +397,9 @@
@Test
public void testCpuFreqTimes_stateBg() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -392,6 +430,9 @@
@Test
public void testCpuFreqTimes_stateCached() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
return;
}
@@ -419,6 +460,124 @@
batteryOffScreenOn();
}
+ @Test
+ public void testCpuFreqTimes_trackingDisabled() throws Exception {
+ if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
+ Log.w(TAG, "Skipping " + testName.getMethodName()
+ + "; freqTimesAvailable=" + sCpuFreqTimesAvailable
+ + ", procStateTimesAvailable=" + sPerProcStateTimesAvailable);
+ return;
+ }
+
+ final String bstatsConstants = Settings.Global.getString(sContext.getContentResolver(),
+ Settings.Global.BATTERY_STATS_CONSTANTS);
+ try {
+ batteryOnScreenOn();
+ forceStop();
+ resetBatteryStats();
+ final long[] initialSnapshot = getAllCpuFreqTimes(sTestPkgUid);
+ assertNull("Initial snapshot should be null, initial="
+ + Arrays.toString(initialSnapshot), initialSnapshot);
+ assertNull("Initial top state snapshot should be null",
+ getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP));
+
+ doSomeWork(PROCESS_STATE_TOP);
+ forceStop();
+
+ final long[] cpuTimesMs = getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP);
+ final String msgCpuTimes = getAllCpuTimesMsg();
+ assertCpuTimesValid(cpuTimesMs);
+ long actualCpuTimeMs = 0;
+ for (int i = 0; i < cpuTimesMs.length / 2; ++i) {
+ actualCpuTimeMs += cpuTimesMs[i];
+ }
+ assertApproximateValue("Incorrect total cpu time, " + msgCpuTimes,
+ WORK_DURATION_MS, actualCpuTimeMs);
+
+ updateTrackPerProcStateCpuTimesSetting(bstatsConstants, false);
+
+ doSomeWork(PROCESS_STATE_TOP);
+ forceStop();
+
+ final long[] cpuTimesMs2 = getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP);
+ assertCpuTimesValid(cpuTimesMs2);
+ assertCpuTimesEqual(cpuTimesMs2, cpuTimesMs, 20,
+ "Unexpected cpu times with tracking off");
+
+ updateTrackPerProcStateCpuTimesSetting(bstatsConstants, true);
+
+ final long[] cpuTimesMs3 = getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP);
+ assertCpuTimesValid(cpuTimesMs3);
+ assertCpuTimesEqual(cpuTimesMs3, cpuTimesMs, 20,
+ "Unexpected cpu times after turning on tracking");
+
+ doSomeWork(PROCESS_STATE_TOP);
+ forceStop();
+
+ final long[] cpuTimesMs4 = getAllCpuFreqTimes(sTestPkgUid, PROCESS_STATE_TOP);
+ assertCpuTimesValid(cpuTimesMs4);
+ actualCpuTimeMs = 0;
+ for (int i = 0; i < cpuTimesMs.length / 2; ++i) {
+ actualCpuTimeMs += cpuTimesMs[i];
+ }
+ assertApproximateValue("Incorrect total cpu time, " + msgCpuTimes,
+ 2 * WORK_DURATION_MS, actualCpuTimeMs);
+
+ batteryOffScreenOn();
+ } finally {
+ Settings.Global.putString(sContext.getContentResolver(),
+ Settings.Global.BATTERY_STATS_CONSTANTS, bstatsConstants);
+ }
+ }
+
+ private void assertCpuTimesEqual(long[] actual, long[] expected, long delta, String errMsg) {
+ for (int i = actual.length - 1; i >= 0; --i) {
+ if (actual[i] > expected[i] + delta || actual[i] < expected[i]) {
+ fail(errMsg + ", actual=" + actual + ", expected=" + expected + ", delta=" + delta);
+ }
+ }
+ }
+
+ private void updateTrackPerProcStateCpuTimesSetting(String originalConstants, boolean enabled)
+ throws Exception {
+ final String newConstants;
+ final String setting = KEY_TRACK_CPU_TIMES_BY_PROC_STATE + "=" + enabled;
+ if (originalConstants == null || "null".equals(originalConstants)) {
+ newConstants = setting;
+ } else if (originalConstants.contains(KEY_TRACK_CPU_TIMES_BY_PROC_STATE)) {
+ newConstants = originalConstants.replaceAll(
+ KEY_TRACK_CPU_TIMES_BY_PROC_STATE + "=(true|false)", setting);
+ } else {
+ newConstants = originalConstants + "," + setting;
+ }
+ Settings.Global.putString(sContext.getContentResolver(),
+ Settings.Global.BATTERY_STATS_CONSTANTS, newConstants);
+ assertTrackPerProcStateCpuTimesSetting(enabled);
+ }
+
+ private void assertTrackPerProcStateCpuTimesSetting(boolean enabled) throws Exception {
+ final String expectedValue = Boolean.toString(enabled);
+ assertDelayedCondition("Unexpected value for " + KEY_TRACK_CPU_TIMES_BY_PROC_STATE, () -> {
+ final String actualValue = getSettingValueFromDump(KEY_TRACK_CPU_TIMES_BY_PROC_STATE);
+ return expectedValue.equals(actualValue)
+ ? null : "expected=" + expectedValue + ", actual=" + actualValue;
+ }, SETTING_UPDATE_TIMEOUT_MS, SETTING_UPDATE_CHECK_INTERVAL_MS);
+ }
+
+ private String getSettingValueFromDump(String key) throws Exception {
+ final String settingsDump = executeCmdSilent("dumpsys batterystats --settings");
+ final TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter('\n');
+ splitter.setString(settingsDump);
+ String next;
+ while (splitter.hasNext()) {
+ next = splitter.next();
+ if (next.startsWith(key)) {
+ return next.split("=")[1];
+ }
+ }
+ return null;
+ }
+
private void assertCpuTimesValid(long[] cpuTimes) {
assertNotNull(cpuTimes);
for (int i = 0; i < cpuTimes.length; ++i) {
@@ -750,13 +909,18 @@
}
private void assertDelayedCondition(String errMsgPrefix, ExpectedCondition condition)
- throws Exception {
- final long endTime = SystemClock.uptimeMillis() + GENERAL_TIMEOUT_MS;
+ throws Exception {
+ assertDelayedCondition(errMsgPrefix, condition, GENERAL_TIMEOUT_MS, GENERAL_INTERVAL_MS);
+ }
+
+ private void assertDelayedCondition(String errMsgPrefix, ExpectedCondition condition,
+ long timeoutMs, long checkIntervalMs) throws Exception {
+ final long endTime = SystemClock.uptimeMillis() + timeoutMs;
while (SystemClock.uptimeMillis() <= endTime) {
if (condition.getErrIfNotTrue() == null) {
return;
}
- SystemClock.sleep(GENERAL_INTERVAL_MS);
+ SystemClock.sleep(checkIntervalMs);
}
final String errMsg = condition.getErrIfNotTrue();
if (errMsg != null) {
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
index 27aec56..37b4e41a 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -16,7 +16,9 @@
package com.android.internal.os;
+import static android.os.BatteryStats.STATS_CURRENT;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
+import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
import static com.android.internal.os.BatteryStatsImpl.TimeBase;
@@ -61,7 +63,6 @@
private static final long[] COUNTS = {1111, 2222, 3333, 4444};
private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
- private static final long[] PLUGGED_COUNTS = {9999, 11111, 22222, 33333};
private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
private static final long[] ZEROES = {0, 0, 0, 0};
@@ -83,11 +84,10 @@
parcel.setDataPosition(0);
// Now clear counterArray and verify values are read from parcel correctly.
- updateCounts(null, null, null, null);
+ updateCounts(null, null, null);
mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
"Unexpected unpluggedCounts");
parcel.recycle();
@@ -101,11 +101,10 @@
parcel.setDataPosition(0);
// Now clear counterArray and verify values are read from parcel correctly.
- updateCounts(null, null, null, null);
+ updateCounts(null, null, null);
mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
parcel.recycle();
}
@@ -116,8 +115,7 @@
mCounterArray.onTimeStarted(0, 0, 0);
assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
- assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+ assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts,
"Unexpected unpluggedCounts");
}
@@ -127,7 +125,6 @@
mCounterArray.onTimeStopped(0, 0, 0);
assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
"Unexpected unpluggedCounts");
}
@@ -137,24 +134,50 @@
initializeCounterArrayWithDefaultValues();
when(mTimeBase.isRunning()).thenReturn(false);
- long[] actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
- long[] expectedVal = PLUGGED_COUNTS;
- assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+ assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
+ "Unexpected values");
+ assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
+ mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
+ assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
+ mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
when(mTimeBase.isRunning()).thenReturn(true);
- actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
- expectedVal = COUNTS;
- assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+ assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
+ "Unexpected values");
+ assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
+ mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
+ assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
+ mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
+ }
+
+ private long[] subtract(long[] val, long[] toSubtract) {
+ final long[] result = val.clone();
+ if (toSubtract != null) {
+ for (int i = val.length - 1; i >= 0; --i) {
+ result[i] -= toSubtract[i];
+ }
+ }
+ return result;
}
@Test
public void testAddCountLocked() {
+ updateCounts(null, null, null);
final long[] deltas = {123, 234, 345, 456};
when(mTimeBase.isRunning()).thenReturn(true);
mCounterArray.addCountLocked(deltas);
assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(null, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+ assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+
+ updateCounts(null, null, null);
+ mCounterArray.addCountLocked(deltas, false);
+ assertArrayEquals(null, mCounterArray.mCounts, "Unexpected counts");
+ assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+ assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+ mCounterArray.addCountLocked(deltas, true);
+ assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
+ assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
initializeCounterArrayWithDefaultValues();
@@ -165,7 +188,18 @@
mCounterArray.addCountLocked(deltas);
assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+ assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+ "Unexpected unpluggedCounts");
+
+ initializeCounterArrayWithDefaultValues();
+ mCounterArray.addCountLocked(deltas, false);
+ assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+ assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+ assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+ "Unexpected unpluggedCounts");
+ mCounterArray.addCountLocked(deltas, true);
+ assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
+ assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
"Unexpected unpluggedCounts");
}
@@ -177,7 +211,6 @@
mCounterArray.reset(false /* detachIfReset */);
assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
verifyZeroInteractions(mTimeBase);
@@ -186,7 +219,6 @@
mCounterArray.reset(true /* detachIfReset */);
assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
- assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
verify(mTimeBase).remove(mCounterArray);
verifyNoMoreInteractions(mTimeBase);
@@ -200,7 +232,7 @@
}
private void initializeCounterArrayWithDefaultValues() {
- updateCounts(COUNTS, LOADED_COUNTS, PLUGGED_COUNTS, UNPLUGGED_COUNTS);
+ updateCounts(COUNTS, LOADED_COUNTS, UNPLUGGED_COUNTS);
}
private void assertArrayEquals(long[] expected, long[] actual, String msg) {
@@ -208,11 +240,9 @@
+ ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
}
- private void updateCounts(long[] counts, long[] loadedCounts,
- long[] pluggedCounts, long[] unpluggedCounts) {
- mCounterArray.mCounts = counts;
- mCounterArray.mLoadedCounts = loadedCounts;
- mCounterArray.mPluggedCounts = pluggedCounts;
- mCounterArray.mUnpluggedCounts = unpluggedCounts;
+ private void updateCounts(long[] counts, long[] loadedCounts, long[] unpluggedCounts) {
+ mCounterArray.mCounts = counts == null ? null : counts.clone();
+ mCounterArray.mLoadedCounts = loadedCounts == null ? null : loadedCounts.clone();
+ mCounterArray.mUnpluggedCounts = unpluggedCounts == null ? null : unpluggedCounts.clone();
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index f19ff67..6c5a2aa 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -139,12 +139,19 @@
}
@Override
- public Future<?> scheduleReadProcStateCpuTimes() {
+ public Future<?> scheduleCpuSyncDueToSettingChange() {
return null;
}
@Override
- public Future<?> scheduleCopyFromAllUidsCpuTimes() {
+ public Future<?> scheduleReadProcStateCpuTimes(
+ boolean onBattery, boolean onBatteryScreenOff) {
+ return null;
+ }
+
+ @Override
+ public Future<?> scheduleCopyFromAllUidsCpuTimes(
+ boolean onBattery, boolean onBatteryScreenOff) {
return null;
}
diff --git a/core/tests/privacytests/Android.mk b/core/tests/privacytests/Android.mk
index 7b11225..7bba417 100644
--- a/core/tests/privacytests/Android.mk
+++ b/core/tests/privacytests/Android.mk
@@ -13,4 +13,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksPrivacyLibraryTests
+LOCAL_CERTIFICATE := platform
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
include $(BUILD_PACKAGE)
diff --git a/core/tests/privacytests/AndroidTest.xml b/core/tests/privacytests/AndroidTest.xml
new file mode 100644
index 0000000..a43f48e
--- /dev/null
+++ b/core/tests/privacytests/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Privacy Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FrameworksPrivacyLibraryTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.coretests.privacy" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 1affba0..d2c855b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -112,6 +112,10 @@
<group gid="media" />
</permission>
+ <permission name="android.permission.USE_RESERVED_DISK">
+ <group gid="reserved_disk" />
+ </permission>
+
<!-- These are permissions that were mapped to gids but we need
to keep them here until an upgrade from L to the current
version is to be supported. These permissions are built-in
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 7bb2859..4732bec 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -136,6 +136,7 @@
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
<privapp-permissions package="com.android.phone">
@@ -181,6 +182,7 @@
<privapp-permissions package="com.android.providers.calendar">
<permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
<privapp-permissions package="com.android.providers.contacts">
@@ -189,6 +191,7 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
<privapp-permissions package="com.android.providers.downloads">
@@ -203,12 +206,14 @@
<permission name="android.permission.ACCESS_MTP"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
</privapp-permissions>
<privapp-permissions package="com.android.providers.telephony">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
<privapp-permissions package="com.android.provision">
@@ -253,6 +258,7 @@
<permission name="android.permission.SET_TIME"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.USER_ACTIVITY"/>
<permission name="android.permission.WRITE_APN_SETTINGS"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
@@ -316,6 +322,7 @@
<permission name="android.permission.STOP_APP_SWITCHES"/>
<permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
@@ -329,6 +336,7 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
@@ -365,6 +373,7 @@
<permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_DREAM_STATE"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
diff --git a/docs/html/_shared/_reference-head-tags.html b/docs/html/_shared/_reference-head-tags.html
new file mode 100644
index 0000000..f66a7b7
--- /dev/null
+++ b/docs/html/_shared/_reference-head-tags.html
@@ -0,0 +1,8 @@
+ <!-- Added to Gerrit so we can stage reference docs directly from
+ Android builds; this file should *not* be migrated to Piper -->
+
+ <meta name="top_category" value="develop" />
+ <meta name="subcategory" value="reference" />
+ <meta name="book_path" value="{% if book_path %}{{ book_path }}{% else %}/reference/_book.yaml{% endif %}" />
+ <meta name="project_path" value="/reference/_project.yaml" />
+ <meta name="page_type" value="reference" />
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 60416a7..419e2b7 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -16,29 +16,45 @@
package android.graphics;
+import static android.system.OsConstants.SEEK_SET;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RawRes;
+import android.content.ContentResolver;
+import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.NinePatchDrawable;
+import android.net.Uri;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import libcore.io.IoUtils;
+import dalvik.system.CloseGuard;
import java.nio.ByteBuffer;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ArrayIndexOutOfBoundsException;
+import java.lang.AutoCloseable;
import java.lang.NullPointerException;
import java.lang.RuntimeException;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Class for decoding images as {@link Bitmap}s or {@link Drawable}s.
* @hide
*/
-public final class ImageDecoder {
+public final class ImageDecoder implements AutoCloseable {
/**
* Source of the encoded image data.
*/
@@ -47,10 +63,7 @@
Resources getResources() { return null; }
/* @hide */
- void close() {}
-
- /* @hide */
- abstract ImageDecoder createImageDecoder();
+ abstract ImageDecoder createImageDecoder() throws IOException;
};
private static class ByteArraySource extends Source {
@@ -64,7 +77,7 @@
private final int mLength;
@Override
- public ImageDecoder createImageDecoder() {
+ public ImageDecoder createImageDecoder() throws IOException {
return nCreate(mData, mOffset, mLength);
}
}
@@ -76,7 +89,7 @@
private final ByteBuffer mBuffer;
@Override
- public ImageDecoder createImageDecoder() {
+ public ImageDecoder createImageDecoder() throws IOException {
if (!mBuffer.isDirect() && mBuffer.hasArray()) {
int offset = mBuffer.arrayOffset() + mBuffer.position();
int length = mBuffer.limit() - mBuffer.position();
@@ -86,61 +99,110 @@
}
}
- private static class ResourceSource extends Source {
- ResourceSource(Resources res, int resId)
- throws Resources.NotFoundException {
- // Test that the resource can be found.
- InputStream is = null;
+ private static class ContentResolverSource extends Source {
+ ContentResolverSource(ContentResolver resolver, Uri uri) {
+ mResolver = resolver;
+ mUri = uri;
+ }
+
+ private final ContentResolver mResolver;
+ private final Uri mUri;
+
+ @Override
+ public ImageDecoder createImageDecoder() throws IOException {
+ AssetFileDescriptor assetFd = null;
try {
- is = res.openRawResource(resId);
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- }
+ if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) {
+ assetFd = mResolver.openTypedAssetFileDescriptor(mUri,
+ "image/*", null);
+ } else {
+ assetFd = mResolver.openAssetFileDescriptor(mUri, "r");
}
+ } catch (FileNotFoundException e) {
+ // Some images cannot be opened as AssetFileDescriptors (e.g.
+ // bmp, ico). Open them as InputStreams.
+ InputStream is = mResolver.openInputStream(mUri);
+ if (is == null) {
+ throw new FileNotFoundException(mUri.toString());
+ }
+
+ return createFromStream(is);
}
+ final FileDescriptor fd = assetFd.getFileDescriptor();
+ final long offset = assetFd.getStartOffset();
+
+ ImageDecoder decoder = null;
+ try {
+ try {
+ Os.lseek(fd, offset, SEEK_SET);
+ decoder = nCreate(fd);
+ } catch (ErrnoException e) {
+ decoder = createFromStream(new FileInputStream(fd));
+ }
+ } finally {
+ if (decoder == null) {
+ IoUtils.closeQuietly(assetFd);
+ } else {
+ decoder.mAssetFd = assetFd;
+ }
+ }
+ return decoder;
+ }
+ }
+
+ private static ImageDecoder createFromStream(InputStream is) throws IOException {
+ // Arbitrary size matches BitmapFactory.
+ byte[] storage = new byte[16 * 1024];
+ ImageDecoder decoder = null;
+ try {
+ decoder = nCreate(is, storage);
+ } finally {
+ if (decoder == null) {
+ IoUtils.closeQuietly(is);
+ } else {
+ decoder.mInputStream = is;
+ decoder.mTempStorage = storage;
+ }
+ }
+
+ return decoder;
+ }
+
+ private static class ResourceSource extends Source {
+ ResourceSource(Resources res, int resId) {
mResources = res;
mResId = resId;
}
final Resources mResources;
final int mResId;
- // This is just stored here in order to keep the underlying Asset
- // alive. FIXME: Can I access the Asset (and keep it alive) without
- // this object?
- InputStream mInputStream;
@Override
public Resources getResources() { return mResources; }
@Override
- public ImageDecoder createImageDecoder() {
- // FIXME: Can I bypass creating the stream?
+ public ImageDecoder createImageDecoder() throws IOException {
+ // This is just used in order to access the underlying Asset and
+ // keep it alive. FIXME: Can we skip creating this object?
+ InputStream is = null;
+ ImageDecoder decoder = null;
try {
- mInputStream = mResources.openRawResource(mResId);
- } catch (Resources.NotFoundException e) {
- // This should never happen, since we already tested in the
- // constructor.
- }
- if (!(mInputStream instanceof AssetManager.AssetInputStream)) {
- // This should never happen.
- throw new RuntimeException("Resource is not an asset?");
- }
- long asset = ((AssetManager.AssetInputStream) mInputStream).getNativeAsset();
- return nCreate(asset);
- }
-
- @Override
- public void close() {
- try {
- mInputStream.close();
- } catch (IOException e) {
+ is = mResources.openRawResource(mResId);
+ if (!(is instanceof AssetManager.AssetInputStream)) {
+ // This should never happen.
+ throw new RuntimeException("Resource is not an asset?");
+ }
+ long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
+ decoder = nCreate(asset);
} finally {
- mInputStream = null;
+ if (decoder == null) {
+ IoUtils.closeQuietly(is);
+ } else {
+ decoder.mInputStream = is;
+ }
}
+ return decoder;
}
}
@@ -148,29 +210,52 @@
* Contains information about the encoded image.
*/
public static class ImageInfo {
+ /**
+ * Width of the image, without scaling or cropping.
+ */
public final int width;
- public final int height;
- // TODO?: Add more info? mimetype, ninepatch etc?
- ImageInfo(int width, int height) {
- this.width = width;
- this.height = height;
+ /**
+ * Height 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;
+ }
+
+ /**
+ * The mimeType of the image, if known.
+ */
+ public String getMimeType() {
+ return decoder.getMimeType();
}
};
/**
- * Used if the provided data is incomplete.
+ * Supplied to onPartialImage if the provided data is incomplete.
+ *
+ * Will never be thrown by ImageDecoder.
*
* There may be a partial image to display.
*/
- public class IncompleteException extends Exception {};
+ public static class IncompleteException extends IOException {};
/**
* Used if the provided data is corrupt.
*
- * There may be a partial image to display.
+ * May be thrown if there is nothing to display.
+ *
+ * If supplied to onPartialImage, there may be a correct partial image to
+ * display.
*/
- public class CorruptException extends Exception {};
+ public static class CorruptException extends IOException {};
/**
* Optional listener supplied to {@link #decodeDrawable} or
@@ -190,18 +275,21 @@
/**
* Optional listener supplied to the ImageDecoder.
*/
- public static interface OnExceptionListener {
+ public static interface OnPartialImageListener {
/**
- * Called when there is a problem in the stream or in the data.
- * FIXME: Or do not allow streams?
- * FIXME: Report how much of the image has been decoded?
+ * Called when there is only a partial image to display.
*
- * @param e Exception containing information about the error.
- * @return True to create and return a {@link Drawable}/
- * {@link Bitmap} with partial data. False to return
- * {@code null}. True is the default.
+ * 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.
+ *
+ * @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}.
*/
- public boolean onException(Exception e);
+ public boolean onPartialImage(IOException e);
};
// Fields
@@ -218,12 +306,18 @@
private boolean mAsAlphaMask = false;
private Rect mCropRect;
- private PostProcess mPostProcess;
- private OnExceptionListener mOnExceptionListener;
+ private PostProcess mPostProcess;
+ private OnPartialImageListener mOnPartialImageListener;
+ // Objects for interacting with the input.
+ private InputStream mInputStream;
+ private byte[] mTempStorage;
+ private AssetFileDescriptor mAssetFd;
+ private final AtomicBoolean mClosed = new AtomicBoolean();
+ private final CloseGuard mCloseGuard = CloseGuard.get();
/**
- * Private constructor called by JNI. {@link #recycle} must be
+ * Private constructor called by JNI. {@link #close} must be
* called after decoding to delete native resources.
*/
@SuppressWarnings("unused")
@@ -233,6 +327,20 @@
mHeight = height;
mDesiredWidth = width;
mDesiredHeight = height;
+ mCloseGuard.open("close");
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+
+ close();
+ } finally {
+ super.finalize();
+ }
}
/**
@@ -243,14 +351,28 @@
* // FIXME: Can be an @DrawableRes?
* @return a new Source object, which can be passed to
* {@link #decodeDrawable} or {@link #decodeBitmap}.
- * @throws Resources.NotFoundException if the asset does not exist.
*/
+ @NonNull
public static Source createSource(@NonNull Resources res, @RawRes int resId)
- throws Resources.NotFoundException {
+ {
return new ResourceSource(res, resId);
}
/**
+ * Create a new {@link Source} from a {@link android.net.Uri}.
+ *
+ * @param cr to retrieve from.
+ * @param uri of the image file.
+ * @return a new Source object, which can be passed to
+ * {@link #decodeDrawable} or {@link #decodeBitmap}.
+ */
+ @NonNull
+ public static Source createSource(@NonNull ContentResolver cr,
+ @NonNull Uri uri) {
+ return new ContentResolverSource(cr, uri);
+ }
+
+ /**
* 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
@@ -260,7 +382,6 @@
* @throws ArrayIndexOutOfBoundsException if offset and length are
* not within data.
*/
- // TODO: Overloads that don't use offset, length
public static Source createSource(@NonNull byte[] data, int offset,
int length) throws ArrayIndexOutOfBoundsException {
if (data == null) {
@@ -275,6 +396,13 @@
}
/**
+ * See {@link #createSource(byte[], int, int).
+ */
+ public static Source createSource(@NonNull byte[] data) {
+ return createSource(data, 0, data.length);
+ }
+
+ /**
* Create a new {@link Source} from a {@link java.nio.ByteBuffer}.
*
* The returned {@link Source} effectively takes ownership of the
@@ -307,7 +435,7 @@
+ "provided " + sampleSize);
}
if (mNativePtr == 0) {
- throw new IllegalStateException("ImageDecoder is recycled!");
+ throw new IllegalStateException("ImageDecoder is closed!");
}
return nGetSampledSize(mNativePtr, sampleSize);
@@ -433,13 +561,13 @@
}
/**
- * Set (replace) the {@link OnExceptionListener} on this object.
+ * Set (replace) the {@link OnPartialImageListener} on this object.
*
* Will be called if there is an error in the input. Without one, a
* partial {@link Bitmap} will be created.
*/
- public void setOnExceptionListener(OnExceptionListener l) {
- mOnExceptionListener = l;
+ public void setOnPartialImageListener(OnPartialImageListener l) {
+ mOnPartialImageListener = l;
}
/**
@@ -500,24 +628,26 @@
mAsAlphaMask = true;
}
- /**
- * Clean up resources.
- *
- * ImageDecoder has a private constructor, and will always be recycled
- * by decodeDrawable or decodeBitmap which creates it, so there is no
- * need for a finalizer.
- */
- private void recycle() {
- if (mNativePtr == 0) {
+ @Override
+ public void close() {
+ mCloseGuard.close();
+ if (!mClosed.compareAndSet(false, true)) {
return;
}
- nRecycle(mNativePtr);
+ nClose(mNativePtr);
mNativePtr = 0;
+
+ IoUtils.closeQuietly(mInputStream);
+ IoUtils.closeQuietly(mAssetFd);
+
+ mInputStream = null;
+ mAssetFd = null;
+ mTempStorage = null;
}
private void checkState() {
if (mNativePtr == 0) {
- throw new IllegalStateException("Cannot reuse ImageDecoder.Source!");
+ throw new IllegalStateException("Cannot use closed ImageDecoder!");
}
checkSubset(mDesiredWidth, mDesiredHeight, mCropRect);
@@ -547,48 +677,55 @@
}
/**
- * Create a {@link Drawable}.
+ * Create a {@link Drawable} from a {@code Source}.
+ *
+ * @param src representing the encoded image.
+ * @param listener for learning the {@link ImageInfo} and changing any
+ * default settings on the {@code ImageDecoder}. If not {@code null},
+ * this will be called on the same thread as {@code decodeDrawable}
+ * before that method returns.
+ * @return Drawable for displaying the image.
+ * @throws IOException if {@code src} is not found, is an unsupported
+ * format, or cannot be decoded for any reason.
*/
- public static Drawable decodeDrawable(Source src, OnHeaderDecodedListener listener) {
- ImageDecoder decoder = src.createImageDecoder();
- if (decoder == null) {
- return null;
- }
-
- if (listener != null) {
- ImageInfo info = new ImageInfo(decoder.mWidth, decoder.mHeight);
- listener.onHeaderDecoded(info, decoder);
- }
-
- decoder.checkState();
-
- if (decoder.mRequireUnpremultiplied) {
- // Though this could be supported (ignored) for opaque images, it
- // seems better to always report this error.
- throw new IllegalStateException("Cannot decode a Drawable with" +
- " unpremultiplied pixels!");
- }
-
- if (decoder.mMutable) {
- throw new IllegalStateException("Cannot decode a mutable Drawable!");
- }
-
- try {
- Bitmap bm = nDecodeBitmap(decoder.mNativePtr,
- decoder.mOnExceptionListener,
- decoder.mPostProcess,
- decoder.mDesiredWidth, decoder.mDesiredHeight,
- decoder.mCropRect,
- false, // decoder.mMutable
- decoder.mAllocator,
- false, // decoder.mRequireUnpremultiplied
- decoder.mPreferRamOverQuality,
- decoder.mAsAlphaMask
- );
- if (bm == null) {
- return null;
+ @NonNull
+ 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.checkState();
+
+ if (decoder.mRequireUnpremultiplied) {
+ // Though this could be supported (ignored) for opaque images,
+ // it seems better to always report this error.
+ throw new IllegalStateException("Cannot decode a Drawable " +
+ "with unpremultiplied pixels!");
+ }
+
+ if (decoder.mMutable) {
+ throw new IllegalStateException("Cannot decode a mutable " +
+ "Drawable!");
+ }
+
+ Bitmap bm = nDecodeBitmap(decoder.mNativePtr,
+ decoder.mOnPartialImageListener,
+ decoder.mPostProcess,
+ decoder.mDesiredWidth,
+ decoder.mDesiredHeight,
+ decoder.mCropRect,
+ false, // mMutable
+ decoder.mAllocator,
+ false, // mRequireUnpremultiplied
+ decoder.mPreferRamOverQuality,
+ decoder.mAsAlphaMask);
Resources res = src.getResources();
if (res == null) {
bm.setDensity(Bitmap.DENSITY_NONE);
@@ -606,60 +743,91 @@
// TODO: Handle animation.
return new BitmapDrawable(res, bm);
- } finally {
- decoder.recycle();
- src.close();
}
}
/**
- * Create a {@link Bitmap}.
+ * See {@link #decodeDrawable(Source, OnHeaderDecodedListener)}.
*/
- public static Bitmap decodeBitmap(Source src, OnHeaderDecodedListener listener) {
- ImageDecoder decoder = src.createImageDecoder();
- if (decoder == null) {
- return null;
- }
+ @NonNull
+ public static Drawable decodeDrawable(@NonNull Source src)
+ throws IOException {
+ return decodeDrawable(src, null);
+ }
- if (listener != null) {
- ImageInfo info = new ImageInfo(decoder.mWidth, decoder.mHeight);
- listener.onHeaderDecoded(info, decoder);
- }
+ /**
+ * Create a {@link Bitmap} from a {@code Source}.
+ *
+ * @param src representing the encoded image.
+ * @param listener for learning the {@link ImageInfo} and changing any
+ * default settings on the {@code ImageDecoder}. If not {@code null},
+ * this will be called on the same thread as {@code decodeBitmap}
+ * before that method returns.
+ * @return Bitmap containing the image.
+ * @throws IOException if {@code src} is not found, is an unsupported
+ * format, or cannot be decoded for any reason.
+ */
+ @NonNull
+ 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.checkState();
+ decoder.checkState();
- try {
return nDecodeBitmap(decoder.mNativePtr,
- decoder.mOnExceptionListener,
+ decoder.mOnPartialImageListener,
decoder.mPostProcess,
- decoder.mDesiredWidth, decoder.mDesiredHeight,
+ decoder.mDesiredWidth,
+ decoder.mDesiredHeight,
decoder.mCropRect,
decoder.mMutable,
decoder.mAllocator,
decoder.mRequireUnpremultiplied,
decoder.mPreferRamOverQuality,
decoder.mAsAlphaMask);
- } finally {
- decoder.recycle();
- src.close();
}
}
- private static native ImageDecoder nCreate(long asset);
+ private String getMimeType() {
+ return nGetMimeType(mNativePtr);
+ }
+
+ /**
+ * See {@link #decodeBitmap(Source, OnHeaderDecodedListener)}.
+ */
+ @NonNull
+ public static Bitmap decodeBitmap(@NonNull Source src) throws IOException {
+ return decodeBitmap(src, null);
+ }
+
+ private static native ImageDecoder nCreate(long asset) throws IOException;
private static native ImageDecoder nCreate(ByteBuffer buffer,
int position,
- int limit);
+ int limit) throws IOException;
private static native ImageDecoder nCreate(byte[] data, int offset,
- int length);
+ int length) throws IOException;
+ private static native ImageDecoder nCreate(InputStream is, byte[] storage);
+ private static native ImageDecoder nCreate(FileDescriptor fd) throws IOException;
+ @NonNull
private static native Bitmap nDecodeBitmap(long nativePtr,
- OnExceptionListener listener,
+ OnPartialImageListener listener,
PostProcess postProcess,
int width, int height,
Rect cropRect, boolean mutable,
int allocator, boolean requireUnpremul,
- boolean preferRamOverQuality, boolean asAlphaMask);
+ 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 void nRecycle(long nativePtr);
+ private static native void nClose(long nativePtr);
+ private static native String nGetMimeType(long nativePtr);
}
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index c329918..749b7594 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -819,8 +819,10 @@
if (bitmapWidth > maxWidth || bitmapHeight > maxHeight) {
float scale = Math.min((float) maxWidth / bitmapWidth,
(float) maxHeight / bitmapHeight);
- bitmap = Bitmap.createScaledBitmap(bitmap, (int) (scale * bitmapWidth),
- (int) (scale * bitmapHeight), true /* filter */);
+ bitmap = Bitmap.createScaledBitmap(bitmap,
+ Math.max(1, (int) (scale * bitmapWidth)),
+ Math.max(1, (int) (scale * bitmapHeight)),
+ true /* filter */);
}
return bitmap;
}
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 87edd69..c7a3014 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -64,7 +64,6 @@
size_t keySize = key.size();
std::lock_guard<std::mutex> lock(mMutex);
if (!mInitialized) {
- ALOGE("ShaderCache::load not initialized");
return nullptr;
}
@@ -103,7 +102,6 @@
std::lock_guard<std::mutex> lock(mMutex);
if (!mInitialized) {
- ALOGE("ShaderCache::store not initialized");
return;
}
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index d268cf4..49bfe1e 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -37,6 +37,9 @@
// incidentd calls dumpsys for annotated field
SECTION_DUMPSYS = 3;
+
+ // incidentd calls logs for annotated field
+ SECTION_LOG = 4;
}
message SectionFlags {
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index f9075cfd..0990dcc 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -79,6 +79,7 @@
boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
void flushGnssBatch(String packageName);
boolean stopGnssBatch();
+ boolean injectLocation(in Location location);
// --- deprecated ---
List<String> getAllProviders();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 4802b23..f0b2774 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -42,6 +42,7 @@
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.LOCATION_HARDWARE;
/**
* This class provides access to the system location services. These
@@ -882,6 +883,34 @@
requestLocationUpdates(request, null, null, intent);
}
+ /**
+ * Set the last known location with a new location.
+ *
+ * <p>A privileged client can inject a {@link Location} if it has a better estimate of what
+ * the recent location is. This is especially useful when the device boots up and the GPS
+ * chipset is in the process of getting the first fix. If the client has cached the location,
+ * it can inject the {@link Location}, so if an app requests for a {@link Location} from {@link
+ * #getLastKnownLocation(String)}, the location information is still useful before getting
+ * the first fix.</p>
+ *
+ * <p> Useful in products like Auto.
+ *
+ * @param newLocation newly available {@link Location} object
+ * @return true if update was successful, false if not
+ *
+ * @throws SecurityException if no suitable permission is present
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION})
+ public boolean injectLocation(Location newLocation) {
+ try {
+ return mService.injectLocation(newLocation);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private ListenerTransport wrapListener(LocationListener listener, Looper looper) {
if (listener == null) return null;
synchronized (mListeners) {
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 306ed83..c6496eb 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -680,6 +680,21 @@
public static final String KEY_LATENCY = "latency";
/**
+ * An optional key describing the maximum number of non-display-order coded frames.
+ * This is an optional parameter that applies only to video encoders. Application should
+ * check the value for this key in the output format to see if codec will produce
+ * non-display-order coded frames. If encoder supports it, the output frames' order will be
+ * different from the display order and each frame's display order could be retrived from
+ * {@link MediaCodec.BufferInfo#presentationTimeUs}. Before API level 27, application may
+ * receive non-display-order coded frames even though the application did not request it.
+ * Note: Application should not rearrange the frames to display order before feeding them
+ * to {@link MediaMuxer#writeSampleData}.
+ * <p>
+ * The default value is 0.
+ */
+ public static final String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth";
+
+ /**
* A key describing the desired clockwise rotation on an output surface.
* This key is only used when the codec is configured using an output surface.
* The associated value is an integer, representing degrees. Supported values
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
new file mode 100644
index 0000000..b57e02d
--- /dev/null
+++ b/media/java/android/media/update/ApiLoader.java
@@ -0,0 +1,56 @@
+/*
+ * 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.media.update;
+
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+/**
+ * @hide
+ */
+public final class ApiLoader {
+ private static Object sMediaLibrary;
+
+ private static final String UPDATE_PACKAGE = "com.android.media.update";
+ private static final String UPDATE_CLASS = "com.android.media.update.ApiFactory";
+ private static final String UPDATE_METHOD = "initialize";
+
+ private ApiLoader() { }
+
+ public static StaticProvider getProvider(Context context) {
+ try {
+ return (StaticProvider) getMediaLibraryImpl(context);
+ } catch (NameNotFoundException | ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // TODO This method may do I/O; Ensure it does not violate (emit warnings in) strict mode.
+ private static synchronized Object getMediaLibraryImpl(Context appContext)
+ throws NameNotFoundException, ReflectiveOperationException {
+ if (sMediaLibrary != null) return sMediaLibrary;
+
+ // TODO Dynamically find the package name
+ Context libContext = appContext.createPackageContext(UPDATE_PACKAGE,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ sMediaLibrary = libContext.getClassLoader()
+ .loadClass(UPDATE_CLASS)
+ .getMethod(UPDATE_METHOD, Context.class)
+ .invoke(null, appContext);
+ return sMediaLibrary;
+ }
+}
diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java
new file mode 100644
index 0000000..71fbd08
--- /dev/null
+++ b/media/java/android/media/update/MediaController2Provider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.media.update;
+
+import android.annotation.SystemApi;
+import android.media.session.MediaController;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+/**
+ * Interface for connecting the public API to an updatable implementation.
+ *
+ * Each instance object is connected to one corresponding updatable object which implements the
+ * runtime behavior of that class. There should a corresponding provider method for all public
+ * methods.
+ *
+ * All methods behave as per their namesake in the public API.
+ *
+ * @see android.widget.MediaController2
+ *
+ * @hide
+ */
+// TODO @SystemApi
+public interface MediaController2Provider extends ViewProvider {
+ void setController_impl(MediaController controller);
+ void setAnchorView_impl(View view);
+ void show_impl();
+ void show_impl(int timeout);
+ boolean isShowing_impl();
+ void hide_impl();
+ void setPrevNextListeners_impl(OnClickListener next, OnClickListener prev);
+ void showCCButton_impl();
+ boolean isPlaying_impl();
+ int getCurrentPosition_impl();
+ int getBufferPercentage_impl();
+ boolean canPause_impl();
+ boolean canSeekBackward_impl();
+ boolean canSeekForward_impl();
+ void showSubtitle_impl();
+ void hideSubtitle_impl();
+}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
new file mode 100644
index 0000000..19f01c2
--- /dev/null
+++ b/media/java/android/media/update/StaticProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.media.update;
+
+import android.annotation.SystemApi;
+import android.widget.MediaController2;
+
+/**
+ * Interface for connecting the public API to an updatable implementation.
+ *
+ * This interface provides access to constructors and static methods that are otherwise not directly
+ * accessible via an implementation object.
+ *
+ * @hide
+ */
+// TODO @SystemApi
+public interface StaticProvider {
+ MediaController2Provider createMediaController2(
+ MediaController2 instance, ViewProvider superProvider);
+}
diff --git a/media/java/android/media/update/ViewProvider.java b/media/java/android/media/update/ViewProvider.java
new file mode 100644
index 0000000..bc8f203
--- /dev/null
+++ b/media/java/android/media/update/ViewProvider.java
@@ -0,0 +1,51 @@
+/*
+ * 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.media.update;
+
+import android.annotation.SystemApi;
+import android.graphics.Canvas;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+/**
+ * Interface for connecting the public API to an updatable implementation.
+ *
+ * Each instance object is connected to one corresponding updatable object which implements the
+ * runtime behavior of that class. There should a corresponding provider method for all public
+ * methods.
+ *
+ * All methods behave as per their namesake in the public API.
+ *
+ * @see android.view.View
+ *
+ * @hide
+ */
+// TODO @SystemApi
+public interface ViewProvider {
+ // TODO Add more (all?) methods from View
+ void onAttachedToWindow_impl();
+ void onDetachedFromWindow_impl();
+ void onLayout_impl(boolean changed, int left, int top, int right, int bottom);
+ void draw_impl(Canvas canvas);
+ CharSequence getAccessibilityClassName_impl();
+ boolean onTouchEvent_impl(MotionEvent ev);
+ boolean onTrackballEvent_impl(MotionEvent ev);
+ boolean onKeyDown_impl(int keyCode, KeyEvent event);
+ void onFinishInflate_impl();
+ boolean dispatchKeyEvent_impl(KeyEvent event);
+ void setEnabled_impl(boolean enabled);
+}
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 0704e35..61164e0 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -29,13 +29,6 @@
shared_libs: [
"libandroid_runtime",
],
-
- arch: {
- arm: {
- // TODO: This is to work around b/24465209. Remove after root cause is fixed
- ldflags: ["-Wl,--hash-style=both"],
- },
- },
}
// The headers module is in frameworks/native/Android.bp.
diff --git a/packages/BackupRestoreConfirmation/res/values-ar/strings.xml b/packages/BackupRestoreConfirmation/res/values-ar/strings.xml
index 4d4d6be..810b1e7 100644
--- a/packages/BackupRestoreConfirmation/res/values-ar/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ar/strings.xml
@@ -21,7 +21,7 @@
<string name="backup_confirm_text" msgid="1878021282758896593">"تم طلب الاحتفاظ بنسخة احتياطية كاملة من البيانات على كمبيوتر سطح مكتب متصل. هل تريد السماح بإجراء ذلك؟\n\nإذا لم تطلب الاحتفاظ بنسخة احتياطية بنفسك، فلا تسمح بمتابعة العملية."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"الاحتفاظ بنسخة احتياطية من بياناتي"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"عدم النسخ الاحتياطي"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"تم طلب استرداد جميع البيانات بالكامل من كمبيوتر سطح مكتب متصل. هل تريد السماح بإجراء ذلك؟\n\nإذا لم تطلب الاسترداد بنفسك، فلا تسمح بمتابعة العملية. يؤدي لك إلى استبدال أية بيانات حاليًا على الجهاز."</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"تم طلب استرداد جميع البيانات بالكامل من كمبيوتر سطح مكتب متصل. هل تريد السماح بإجراء ذلك؟\n\nإذا لم تطلب الاسترداد بنفسك، فلا تسمح بمتابعة العملية. يؤدي لك إلى استبدال أي بيانات حاليًا على الجهاز."</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"استرداد بياناتي"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"عدم الاسترداد"</string>
<string name="current_password_text" msgid="8268189555578298067">"يُرجى إدخال كلمة مرور النسخ الاحتياطي أدناه:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
index cbc579e..baa4867 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
@@ -18,10 +18,10 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Backup completo"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Restauração completa"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitado um backup completo de todos os dados para um computador conectado. Deseja permitir que isso aconteça?\n\nCaso você não tenha solicitado o backup, não permita que a operação prossiga."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitado um backup completo de todos os dados para um computador conectado. Quer permitir que isso aconteça?\n\nCaso você não tenha solicitado o backup, não permita que a operação prossiga."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Fazer backup de meus dados"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Não fazer backup"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitada uma restauração completa de todos os dados de um computador conectado. Deseja permitir que isso ocorra?\n\nCaso você não tenha solicitado a restauração, não permita que a operação prossiga. Isso substituirá todos os dados existentes no dispositivo!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitada uma restauração completa de todos os dados de um computador conectado. Quer permitir que isso ocorra?\n\nCaso você não tenha solicitado a restauração, não permita que a operação prossiga. Isso substituirá todos os dados existentes no dispositivo!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar meus dados"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Não restaurar"</string>
<string name="current_password_text" msgid="8268189555578298067">"Digite sua senha de backup atual abaixo:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
index cbc579e..baa4867 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
@@ -18,10 +18,10 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Backup completo"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Restauração completa"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitado um backup completo de todos os dados para um computador conectado. Deseja permitir que isso aconteça?\n\nCaso você não tenha solicitado o backup, não permita que a operação prossiga."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitado um backup completo de todos os dados para um computador conectado. Quer permitir que isso aconteça?\n\nCaso você não tenha solicitado o backup, não permita que a operação prossiga."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Fazer backup de meus dados"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Não fazer backup"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitada uma restauração completa de todos os dados de um computador conectado. Deseja permitir que isso ocorra?\n\nCaso você não tenha solicitado a restauração, não permita que a operação prossiga. Isso substituirá todos os dados existentes no dispositivo!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitada uma restauração completa de todos os dados de um computador conectado. Quer permitir que isso ocorra?\n\nCaso você não tenha solicitado a restauração, não permita que a operação prossiga. Isso substituirá todos os dados existentes no dispositivo!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar meus dados"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Não restaurar"</string>
<string name="current_password_text" msgid="8268189555578298067">"Digite sua senha de backup atual abaixo:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
index 530efc0..ed75344 100644
--- a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Kuhifadhi kikamilifu"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Kurejesha kila kitu"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"Ombi la kuhifadhi nakala rudufu kamili za data kwenye eneo kazi la kompyuta iliyounganishwa limewasilishwa. Ungependa shughuli hii ufanyike?\n\n Ikiwa sio wewe uliyewasilisha ombi hili, usikubali shughuli hii iendelee."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"Ombi la kuhifadhi nakala kamili za data kwenye eneo kazi la kompyuta iliyounganishwa limewasilishwa. Ungependa shughuli hii ufanyike?\n\n Ikiwa si wewe uliyewasilisha ombi hili, usikubali shughuli hii iendelee."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Hifadhi nakala ya data yangu"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Usicheleze"</string>
<string name="restore_confirm_text" msgid="7499866728030461776">"Kurejesha kamili kwa data nzima kutoka kwa eneo kazi la kompyuta lililounganishwa limeombwa. Unataka kuruhusu hii kutendeka?\n\n Ikiwa hukuweza kurejesha upya mwenyewe, usiruhusu uendeshaji huu kuendelea. Hii itaweka upya data yoyote iliyo kwenye kifaa hiki sasa!"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 7edbb11..ad2fc24 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -4,12 +4,12 @@
<string name="app_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
<string name="android_system_label" msgid="2797790869522345065">"Mobilni operater"</string>
<string name="portal_notification_id" msgid="5155057562457079297">"Mobilni internet je potrošen"</string>
- <string name="no_data_notification_id" msgid="668400731803969521">"Prijenos mobilnih podataka je deaktiviran"</string>
+ <string name="no_data_notification_id" msgid="668400731803969521">"Prijenos podataka na mobilnoj mreži je deaktiviran"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"Dodirnite da posjetite %s web lokaciju"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Obratite se pružaocu usluga %s"</string>
<string name="no_mobile_data_connection_title" msgid="7449525772416200578">"Nema mobilnog prijenosa podataka"</string>
<string name="no_mobile_data_connection" msgid="544980465184147010">"Dodajte plan prijenosa podataka ili rominga putem operatera %s"</string>
- <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Status mobilnih podataka"</string>
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Status prijenosa podataka na mobilnoj mreži"</string>
<string name="action_bar_label" msgid="4290345990334377177">"Prijava na mobilnu mrežu"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"Mreža kojoj pokušavate pristupiti ima sigurnosnih problema."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index 9217bc4..8f37882 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -42,4 +42,5 @@
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string>
+ <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijani"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index 9217bc4..8f37882 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -42,4 +42,5 @@
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string>
+ <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijani"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 9217bc4..8f37882 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -42,4 +42,5 @@
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string>
+ <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijani"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 9217bc4..8f37882 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -42,4 +42,5 @@
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string>
+ <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijani"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml
index 43d7677..bc1b234 100644
--- a/packages/InputDevices/res/values-en-rXC/strings.xml
+++ b/packages/InputDevices/res/values-en-rXC/strings.xml
@@ -42,4 +42,5 @@
<string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string>
+ <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijani"</string>
</resources>
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index 19e44e3..6feb8a6 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -18,17 +18,26 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res frameworks/support/v7/recyclerview/res
-LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages android.support.v7.recyclerview
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_USE_AAPT2 := true
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += \
- src/com/android/printspooler/renderer/IPdfRenderer.aidl \
- src/com/android/printspooler/renderer/IPdfEditor.aidl
+ src/com/android/printspooler/renderer/IPdfRenderer.aidl \
+ src/com/android/printspooler/renderer/IPdfEditor.aidl
LOCAL_PACKAGE_NAME := PrintSpooler
LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ android-support-v7-recyclerview \
+ android-support-compat \
+ android-support-media-compat \
+ android-support-core-utils \
+ android-support-core-ui \
+ android-support-fragment
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-annotations
include $(BUILD_PACKAGE)
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index eab784d..f1fd93b 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -56,7 +56,7 @@
<string name="print_select_printer" msgid="7388760939873368698">"حدد الطابعة"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"تجاهل الطابعة"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
- <item quantity="zero">لم يتم العثور على أية طابعة (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
+ <item quantity="zero">لم يتم العثور على أي طابعة (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
<item quantity="two">تم العثور على طابعتين (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
<item quantity="few">تم العثور على <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
<item quantity="many">تم العثور على <xliff:g id="COUNT_1">%1$s</xliff:g> طابعة</item>
diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml
index 862d193..7fe9c8c 100644
--- a/packages/PrintSpooler/res/values-mr/strings.xml
+++ b/packages/PrintSpooler/res/values-mr/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"स्पूलर मुद्रण"</string>
+ <string name="app_label" msgid="4469836075319831821">"स्पूलर प्रिंट"</string>
<string name="more_options_button" msgid="2243228396432556771">"अधिक पर्याय"</string>
<string name="label_destination" msgid="9132510997381599275">"गंतव्यस्थान"</string>
<string name="label_copies" msgid="3634531042822968308">"प्रती"</string>
@@ -31,22 +31,22 @@
<string name="template_all_pages" msgid="3322235982020148762">"सर्व <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ची श्रेणी"</string>
<string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string>
- <string name="print_preview" msgid="8010217796057763343">"मुद्रण पूर्वावलोकन"</string>
+ <string name="print_preview" msgid="8010217796057763343">"प्रिंट पूर्वावलोकन"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"पूर्वावलोकनासाठी पीडीएफ व्ह्यूअर इंस्टॉल करा"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"प्रिंटिंग अॅप क्रॅश झाले"</string>
- <string name="generating_print_job" msgid="3119608742651698916">"मुद्रण कार्य व्युत्पन्न करत आहे"</string>
+ <string name="generating_print_job" msgid="3119608742651698916">"प्रिंट कार्य व्युत्पन्न करत आहे"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"पीडीएफ म्हणून सेव्ह करा"</string>
<string name="all_printers" msgid="5018829726861876202">"सर्व प्रिंटर..."</string>
- <string name="print_dialog" msgid="32628687461331979">"मुद्रण संवाद"</string>
+ <string name="print_dialog" msgid="32628687461331979">"प्रिंट संवाद"</string>
<string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="page_description_template" msgid="6831239682256197161">"<xliff:g id="PAGE_COUNT">%2$d</xliff:g> पैकी <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> पृष्ठ"</string>
<string name="summary_template" msgid="8899734908625669193">"सारांश, प्रती <xliff:g id="COPIES">%1$s</xliff:g>, कागद आकार <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
<string name="expand_handle" msgid="7282974448109280522">"विस्तृत करण्याचे हँडल"</string>
<string name="collapse_handle" msgid="6886637989442507451">"संक्षिप्त करण्याचे हँडल"</string>
- <string name="print_button" msgid="645164566271246268">"मुद्रण करा"</string>
+ <string name="print_button" msgid="645164566271246268">"प्रिंट करा"</string>
<string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ वर सेव्ह करा"</string>
- <string name="print_options_expanded" msgid="6944679157471691859">"मुद्रण पर्याय विस्तृत झाले"</string>
- <string name="print_options_collapsed" msgid="7455930445670414332">"मुद्रण पर्याय संक्षिप्त झाले"</string>
+ <string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट पर्याय विस्तृत झाले"</string>
+ <string name="print_options_collapsed" msgid="7455930445670414332">"प्रिंट पर्याय संक्षिप्त झाले"</string>
<string name="search" msgid="5421724265322228497">"शोध"</string>
<string name="all_printers_label" msgid="3178848870161526399">"सर्व प्रिंटर"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोडा"</string>
@@ -64,9 +64,9 @@
<string name="notification_channel_progress" msgid="872788690775721436">"प्रिंट कार्ये चालवणे"</string>
<string name="notification_channel_failure" msgid="9042250774797916414">"अयशस्वी प्रिंट कार्ये"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"फाईल तयार करणेे शक्य झाले नाही"</string>
- <string name="print_services_disabled_toast" msgid="9089060734685174685">"काही मुद्रण सेवा अक्षम केल्या आहेत"</string>
+ <string name="print_services_disabled_toast" msgid="9089060734685174685">"काही प्रिंट सेवा अक्षम केल्या आहेत"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
- <string name="print_no_print_services" msgid="8561247706423327966">"कोणत्याही मुद्रण सेवा सक्षम केलेल्या नाहीत"</string>
+ <string name="print_no_print_services" msgid="8561247706423327966">"कोणत्याही प्रिंट सेवा सक्षम केलेल्या नाहीत"</string>
<string name="print_no_printers" msgid="4869403323900054866">"कोणतेही प्रिंटर आढळले नाही"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"प्रिंटर जोडू शकत नाही"</string>
<string name="select_to_add_printers" msgid="3800709038689830974">"प्रिंटर जोडण्यासाठी निवडा"</string>
@@ -79,7 +79,7 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item>
</plurals>
- <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> मुद्रण करत आहे"</string>
+ <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट करत आहे"</string>
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करत आहे"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर एरर <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटरने <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> अवरोधित केले"</string>
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
index 9d1c4ca..14f0625 100644
--- a/packages/SettingsLib/common.mk
+++ b/packages/SettingsLib/common.mk
@@ -55,7 +55,6 @@
# Include android-support-v14-preference, if not already included
ifeq (,$(findstring android-support-v14-preference,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_RESOURCE_DIR += frameworks/support/v14/preference/res
LOCAL_AAPT_FLAGS += --extra-packages android.support.v14.preference
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v14-preference
endif
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 5652ad9..ff81fc1 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Wys Bluetooth-toestelle sonder name"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiveer absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktiveer inband-luitoon"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-weergawe"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Kies Bluetooth AVRCP-weergawe"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-oudiokodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontroleer programme wat via ADB/ADT geïnstalleer is vir skadelike gedrag."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-toestelle sonder name (net MAC-adresse) sal gewys word"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiveer die Bluetooth-kenmerk vir absolute volume indien daar volumeprobleme met afgeleë toestelle is, soos onaanvaarbare harde klank of geen beheer nie."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Laat toe dat luitone op die foon op Bluetooth-kopstukke gespeel word"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Plaaslike terminaal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktiveer terminaalprogram wat plaaslike skermtoegang bied"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrolering"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 4aac238..111b7cf 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"የብሉቱዝ መሣሪያዎችን ያለ ስሞች አሳይ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ፍጹማዊ ድምፅን አሰናክል"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"የውስጠ-ሞገድ ማስጮህን አንቃ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"የብሉቱዝ AVRCP ስሪት"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"የብሉቱዝ AVRCP ስሪት ይምረጡ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"የብሉቱዝ ኦዲዮ ኮዴክ"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"በADB/ADT በኩል የተጫኑ መተግበሪያዎች ጎጂ ባህሪ ካላቸው ያረጋግጡ።"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"የብሉቱዝ መሣሪያዎች ያለ ስሞች (MAC አድራሻዎች ብቻ) ይታያሉ"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"እንደ ተቀባይነት በሌለው ደረጃ ድምፁ ከፍ ማለት ወይም መቆጣጠር አለመቻል ያሉ ከሩቅ መሣሪያዎች ጋር የድምፅ ችግር በሚኖርበት ጊዜ የብሉቱዝ ፍጹማዊ ድምፅን ባሕሪ ያሰናክላል።"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"በስልኩ ላይ ያሉ የጥሪ ቅላጼዎች በብሉቱዝ ጆሮ ማዳመጫዎች ላይ እንዲጫወቱ ፍቀድ"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"አካባቢያዊ ተርሚናል"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"የአካባቢያዊ ሼል መዳረሻ የሚያቀርብ የተርሚናል መተግበሪያ አንቃ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"የHDCP ምልከታ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 90cc221..b101a1d 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"عرض أجهزة البلوتوث بدون أسماء"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"تعطيل مستوى الصوت المطلق"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"تمكين الرنين ضمن النطاق الأساسي"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"إصدار Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"اختيار إصدار Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ترميز صوت بلوتوث"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"التحقق من التطبيقات المثبتة عبر ADB/ADT لكشف السلوك الضار"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"سيتم عرض أجهزة البلوتوث بدون أسماء (عناوين MAC فقط)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"لتعطيل ميزة مستوى الصوت المطلق للبلوتوث في حالة حدوث مشكلات متعلقة بمستوى الصوت مع الأجهزة البعيدة مثل مستوى صوت عالٍ بشكل غير مقبول أو نقص إمكانية التحكم في الصوت."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"السماح بتشغيل نغمات الرنين على الهاتف من خلال سماعات الرأس البلوتوث"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"تطبيق طرفي محلي"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"تمكين تطبيق طرفي يوفر إمكانية الدخول إلى واجهة النظام المحلية"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"التحقق من HDCP"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 1053079..03c9b92 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth cihazlarını adsız göstərin"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mütləq səs həcmi deaktiv edin"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Diapazon daxili zəngi aktiv edin"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Versiya"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP Versiyasını seçin"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Adsız Bluetooth cihazları (yalnız MAC ünvanları) göstəriləcək"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Telefondakı bütün melodiyaların Bluetooth qulaqlıqlarında oxudulmasına icazə verin"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Yerli terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Yerli örtük girişini təklif edən terminal tətbiqi aktiv edin"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP yoxlanılır"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 5239f5a..62e4b4c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogućavanje zvonjave na istom kanalu"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija Bluetooth AVRCP-a"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Izaberite verziju Bluetooth AVRCP-a"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Proverava da li su aplikacije instalirane preko ADB-a/ADT-a štetne."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Biće prikazani Bluetooth uređaji bez naziva (samo sa MAC adresama)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava glavno podešavanje jačine zvuka na Bluetooth uređaju u slučaju problema sa jačinom zvuka na daljinskim uređajima, kao što su izuzetno velika jačina zvuka ili nedostatak kontrole."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogućite da se melodija zvona na telefonu pušta preko Bluetooth slušalica"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Omogući aplik. terminala za pristup lokalnom komandnom okruženju"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provera"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index c6aa478..c648ea5 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Паказваць прылады Bluetooth без назваў"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Уключыць унутрыпалосны празвон"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выбраць версію Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодэк Bluetooth Audio"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Праверце прыкладаннi, усталяваныя з дапамогай ADB/ADT, на нестабiльныя паводзiны."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Прылады Bluetooth будуць паказаны без назваў (толькі MAC-адрасы)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Адключыць функцыю абсалютнага гуку Bluetooth у выпадку праблем з гукам на аддаленых прыладах, напр., пры непрымальна высокай гучнасці або адсутнасці кіравання."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дазволіць прайграванне рынгтонаў на тэлефоне праз гарнітуры Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Лакальны тэрмінал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Уключэнне прыкладання тэрмінала, якое прапануе доступ да лакальнай абалонкі"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Праверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c932c83..83c1ec0 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показване на устройствата с Bluetooth без имена"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Деактивиране на пълната сила на звука"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Активиране на звъненето в една и съща честотна лента"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия на AVRCP за Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Избиране на версия на AVRCP за Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек за Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверка на инсталираните чрез ADB/ADT приложения за опасно поведение."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Ще бъдат показани устройствата с Bluetooth без имена (само MAC адресите)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Деактивира функцията на Bluetooth за пълна сила на звука в случай на проблеми със звука на отдалечени устройства, като например неприемливо висока сила на звука или липса на управление."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Разрешаване на мелодиите на телефона да се възпроизвеждат на слушалките с Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Актив. на прил. за терминал с достъп до локалния команден ред"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Проверка с HDCP"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a5c2e41..baf9e2c 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"চূড়ান্ত ভলিউম অক্ষম করুন"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ইন-ব্যান্ড রিং করা সক্ষম করুন"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ব্লুটুথ AVRCP ভার্সন"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ব্লুটুথ AVRCP ভার্সন বেছে নিন"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ব্লুটুথ অডিও কোডেক"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ক্ষতিকারক ক্রিয়াকলাপ করছে কিনা তার জন্য ADB/ADT মারফত ইনস্টল করা অ্যাপ্লিকেশানগুলি চেক করুন।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখানো হবে (শুধুমাত্র MAC ঠিকানা)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য অক্ষম করে৷"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ফোনের রিংটোন ব্লুটুথ হেডসেটে শোনা সক্ষম করুন"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"স্থানীয় টার্মিনাল"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"স্থানীয় শেল অ্যাক্সেসের প্রস্তাব করে এমন টার্মিনাল অ্যাপ্লিকেশন সক্ষম করুন"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP পরীক্ষণ"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index ed0958c..88b01e9 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogući zvono unutar pojasa"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Odaberite Bluetooth AVRCP verziju"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio kodek"</string>
@@ -225,7 +224,7 @@
<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 prometa prisutnog na interfejsu"</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>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li izbrisati trajnu pohranu zapisivača?"</string>
@@ -237,7 +236,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Dozvoli lažne lokacije"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Dozvoli lažne lokacije"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Omogući pregled atributa prikaza"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži mobilne podatke aktivnim, čak i kada je Wi-Fi je aktivan (za brzo prebacivanje između mreža)."</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži prijenos podataka na mobilnoj mreži aktivnim, čak i kada je Wi-Fi je aktivan (za brzo prebacivanje između mreža)."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Koristi hardversko ubrzavanje dijeljenja veze, ako je dostupno"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"Omogućiti otklanjanje grešaka putem uređaja spojenog na USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"Otklanjanje grešaka putem uređaja spojenog na USB je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz zapisnika."</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerava da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamerno ponašanje."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Prikazat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava opciju Bluetooth apsolutne jačine zvuka u slučaju problema s jačinom zvuka na udaljenim uređajima, kao što je neprihvatljivo glasan zvuk ili nedostatak kontrole."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Dopusti da se melodije zvona reproduciranju na Bluetooth slušalicama"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Omogući terminalnu aplik. koja nudi pristup lok. kom. okruženju"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provjeravanje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index e65adcd..48223ce 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostra els dispositius Bluetooth sense el nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactiva el volum absolut"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activa el so al mateix canal"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versió AVRCP de Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versió AVRCP de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Còdec d\'àudio per Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprova les aplicacions instal·lades mitjançant ADB/ADT per detectar possibles comportaments perillosos"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Es mostraran els dispositius Bluetooth sense el nom (només l\'adreça MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva la funció de volum absolut del Bluetooth en cas que es produeixin problemes de volum amb dispositius remots, com ara un volum massa alt o una manca de control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permet que els sons de trucada del telèfon es reprodueixin en auriculars Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activa l\'aplicació de terminal que ofereix accés al shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprovació HDCP"</string>
@@ -358,14 +356,14 @@
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"Temps restant aproximat: <xliff:g id="TIME">^1</xliff:g>"</string>
<string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">^1</xliff:g>"</string>
- <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> per completar la càrrega"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> per completar la pujada"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">^1</xliff:g>"</string>
<string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"Temps restant segons l\'ús que en fas: <xliff:g id="TIME">^1</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g> aproximadament per esgotar la bateria"</string>
<string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">^2</xliff:g>"</string>
<string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g>; temps restant: <xliff:g id="TIME">^2</xliff:g>"</string>
<string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
- <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g> per completar la càrrega"</string>
+ <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g> per completar la pujada"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
<string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 771a32d..88bbaa7 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Zobrazovat zařízení Bluetooth bez názvů"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázat absolutní hlasitost"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Povolit vyzvánění v hovorovém pásmu"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verze profilu Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Vyberte verzi profilu Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio – kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Zařízení Bluetooth se budou zobrazovat bez názvů (pouze adresy MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Zakáže funkci absolutní hlasitosti Bluetooth. Zabrání tak problémům s hlasitostí vzdálených zařízení (jako je příliš vysoká hlasitost nebo nemožnost ovládání)."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Umožňuje přehrávat vyzváněcí tóny z telefonu v náhlavní soupravě Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Místní terminál"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktivovat terminálovou aplikaci pro místní přístup k prostředí shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c3cfdff..6f36bc5 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Vis Bluetooth-enheder uden navne"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiver absolut lydstyrke"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Afspil ringetone via Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version for Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Vælg AVRCP-version for Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-lydcodec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-enheder uden navne (kun MAC-adresser) vises"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillad, at ringetoner på telefonen kan afspilles i Bluetooth-headset"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktivér terminalappen, der giver lokal shell-adgang"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrol"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index d12ac8a..4d53e2d 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-Geräte ohne Namen anzeigen"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Maximallautstärke deaktivieren"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"In-Band-Klingeln aktivieren"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP-Version auswählen"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-Audio-Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Überprüft installierte Apps über ADB/ADT auf schädliches Verhalten"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-Geräte ohne Namen (nur MAC-Adressen) werden angezeigt"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiviert die Bluetooth-Maximallautstärkefunktion, falls auf Remote-Geräten Probleme mit der Lautstärke auftreten, wie beispielsweise übermäßig laute Wiedergabe oder fehlende Kontrolle bei der Steuerung."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Wiedergabe von Smartphone-Klingeltönen auf Bluetooth-Headsets zulassen"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokales Terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Terminal-App mit Zugriff auf lokale Shell aktivieren"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-Prüfung"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 9552c73..e510356 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Εμφάνιση συσκευών Bluetooth χωρίς ονόματα"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Απενεργοποίηση απόλυτης έντασης"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ενεργοποίηση κλήσης εντός εύρους"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Έκδοση AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Επιλογή έκδοσης AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Κωδικοποιητής ήχου Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Έλεγχος εφαρμογών που έχουν εγκατασταθεί μέσω ADB/ADT για επιβλαβή συμπεριφορά."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Θα εμφανιστούν οι συσκευές Bluetooth χωρίς ονόματα (μόνο διευθύνσεις MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Απενεργοποιεί τη δυνατότητα απόλυτης έντασης του Bluetooth σε περίπτωση προβλημάτων έντασης με απομακρυσμένες συσκευές, όπως όταν υπάρχει μη αποδεκτά υψηλή ένταση ή απουσία ελέγχου."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Να επιτρέπεται η αναπαραγωγή των ήχων κλήσης του τηλεφώνου στα ακουστικά Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Τοπική τερματική εφαρμογή"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ενεργοπ.τερμ.εφαρμογής που προσφέρει πρόσβαση στο τοπικό κέλυφος"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Έλεγχος HDCP"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 53b5d9e..a322388 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 53b5d9e..a322388 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 53b5d9e..a322388 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 53b5d9e..a322388 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2b0b6e5..80c2eb8 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behavior."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index c36b3ed..65000b3 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sin nombre"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Habilitar sonido dentro de banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión de AVRCP del Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión de AVRCP del Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec del audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar que las aplicaciones instaladas mediante ADB/ADT no ocasionen daños"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Se mostrarán los dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que los tonos del teléfono suenen en auriculares Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Habilitar aplicac. de terminal que ofrece acceso al shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1f57e48..2a5e41b 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sin nombre"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Habilitar tono de llamada por Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP del Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP del Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprueba las aplicaciones instaladas mediante ADB/ADT para detectar comportamientos dañinos"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Se mostrarán dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que los tonos de llamada del teléfono se reproduzcan en auriculares Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Habilitar aplicación de terminal que ofrece acceso a shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación de HDCP"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 361d14d..a8ac99f 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Kuva Bluetoothi seadmed ilma nimedeta"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Keela absoluutne helitugevus"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Luba ribasisene helisemine"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothi AVRCP versioon"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Valige Bluetoothi AVRCP versioon"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetoothi heli kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolli, kas ADB/ADT-ga installitud rakendused on ohtlikud."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Kuvatakse ilma nimedeta (ainult MAC-aadressidega) Bluetoothi seadmed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Keelatakse Bluetoothi absoluutse helitugevuse funktsioon, kui kaugseadmetega on helitugevuse probleeme (nt liiga vali heli või juhitavuse puudumine)."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Lubab telefonis olevaid helinaid esitada Bluetoothi peakomplektides"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Kohalik terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Luba kohalikku turvalist juurdepääsu pakkuv terminalirakendus"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrollimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 22e9d35..2c81f2e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Erakutsi Bluetooth gailuak izenik gabe"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Gaitu tonuak audio-kanal berean erreproduzitzeko aukera"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Hautatu Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth bidezko audioaren kodeka"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak antzemateko."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth gailuak izenik gabe (MAC helbideak soilik) erakutsiko dira"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desgaitu egiten du Bluetooth bidezko bolumen absolutuaren eginbidea urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Onartu telefonoko tonuak Bluetooth entzungailuetan erreproduzitzeko aukera"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Tokiko terminala"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Gaitu tokiko shell-sarbidea duen terminal-aplikazioa"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP egiaztapena"</string>
@@ -353,7 +351,7 @@
<string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Daltonismoa (gorri-berdeak)"</string>
<string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanopia (gorri-berdeak)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Tritanopia (urdin-horia)"</string>
- <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kolorearen zuzenketa"</string>
+ <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koloreen zuzenketa"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">^1</xliff:g> inguru gelditzen dira"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 35917bb..4f3c77f 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سختافزاری اتصال به اینترنت با تلفن همراه"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"نمایش دستگاههای بلوتوث بدون نام"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"غیرفعال کردن میزان صدای مطلق"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"فعال کردن زنگ زدن درون باندی"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"نسخه AVRCP بلوتوث"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"انتخاب نسخه AVRCP بلوتوث"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"کدک بلوتوث صوتی"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"برنامههای نصب شده از طریق ADB/ADT را ازنظر رفتار مخاطرهآمیز بررسی کنید."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"دستگاههای بلوتوث بدون نام (فقط نشانیهای MAC) نشان داده خواهند شد"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"در صورت وجود مشکل میزان صدا با دستگاههای راه دور مثل میزان صدای بلند ناخوشایند یا عدم کنترل صدا، قابلیت میزان صدای کامل بلوتوث را غیرفعال کنید."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"اجازه میدهد آهنگهای زنگ تلفن در هدستهای بلوتوث پخش شود"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ترمینال محلی"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"فعال کردن ترمینال برنامه کاربردی که دسترسی به برنامه محلی را پیشنهاد میکند"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"بررسی HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 869490a..5932d00 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Näytä nimettömät Bluetooth-laitteet"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Poista yleinen äänenvoimakkuuden säätö käytöstä"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ota käyttöön kaistalla soitto"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothin AVRCP-versio"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Valitse Bluetoothin AVRCP-versio"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-äänen koodekki"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tarkista ADB:n/ADT:n kautta asennetut sovellukset haitallisen toiminnan varalta."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Näytetään Bluetooth-laitteet, joilla ei ole nimiä (vain MAC-osoitteet)."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Bluetoothin yleinen äänenvoimakkuuden säätö poistetaan käytöstä ongelmien välttämiseksi esimerkiksi silloin, kun laitteen äänenvoimakkuus on liian kova tai sitä ei voi säätää."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Salli puhelimen soittoäänten toistaminen Bluetooth-kuulokemikrofoneissa"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Paikallinen pääte"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ota käyttöön päätesov. joka mahdollistaa paikall. liittymäkäytön"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-tarkistus"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6fbe49a..c0c29d3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afficher les appareils Bluetooth sans nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activer la signalisation intra-bande"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version du profil Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Sélectionner la version du profil Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Les appareils Bluetooth sans nom (adresses MAC seulement) seront affichés"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu par Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Autoriser la lecture des sonneries du téléphone sur les écouteurs Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 10addbb..50c99e2 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afficher les appareils Bluetooth sans nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activer la signalisation intra-bande"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Sélectionner la version Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Les appareils Bluetooth seront affichés sans nom (adresse MAC uniquement)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu du Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Autoriser la lecture des sonneries du téléphone sur les casques Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 47d8408..775bbf1 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sen nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activar a función de soar na mesma banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión AVRCP de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Mostraranse dispositivos Bluetooth sen nomes (só enderezos MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que os tons de chamada do teléfono se reproduzan nos auriculares Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index f6bb039..712e57e 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"નામ વિનાના બ્લૂટૂથ ઉપકરણો બતાવો"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ચોક્કસ વૉલ્યૂમને અક્ષમ કરો"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"બેંડમાં રિંગ કરવાનું સક્ષમ કરો"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"બ્લૂટૂથ AVRCP સંસ્કરણ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"બ્લૂટૂથ AVRCP સંસ્કરણ પસંદ કરો"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"બ્લૂટૂથ ઑડિઓ કોડેક"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"હાનિકારક વર્તણૂંક માટે ADB/ADT મારફતે ઇન્સ્ટોલ કરવામાં આવેલી ઍપ્લિકેશનો તપાસો."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"નામ વગરના (ફક્ત MAC ઍડ્રેસવાળા) બ્લૂટૂથ ઉપકરણો બતાવવામાં આવશે"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"રિમોટ ઉપકરણોમાં વધુ પડતું ઊંચું વૉલ્યૂમ અથવા નિયંત્રણની કમી જેવી વૉલ્યૂમની સમસ્યાઓની સ્થિતિમાં બ્લૂટૂથ ચોક્કસ વૉલ્યૂમ સુવિધાને અક્ષમ કરે છે."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ફોનની રિંગટોન બ્લૂટૂથ હૅડસેટ પર વાગવાની મંજૂરી આપો"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"સ્થાનિક ટર્મિનલ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"સ્થાનિક શેલ અૅક્સેસની ઑફર કરતી ટર્મિનલ એપ્લિકેશનને સક્ષમ કરો"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP તપાસણી"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index fcca957..a88abb5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"बिना नाम वाले ब्लूटूथ डिवाइस दिखाएं"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ब्लूटूथ से आवाज़ के नियंत्रण की सुविधा रोकें"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-बैंड रिंग करना चालू करें"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP वर्शन"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटूथ AVRCP वर्शन चुनें"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडियो कोडेक"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"नुकसानदेह व्यवहार के लिए ADB/ADT के द्वारा इंस्टॉल किए गए ऐप्स जाँचें."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"बिना नाम वाले ब्लूटूथ डिवाइस (केवल MAC पते वाले) दिखाए जाएंगे"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे नियंत्रण हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के नियंत्रण की सुविधा रोक देता है."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फ़ोन की रिंगटोन को ब्लूटूथ हेडसेट पर बजने दें"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"लोकल शेल तक पहुंचने की सुविधा देने वाले टर्मिनल ऐप को चालू करें"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP जाँच"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 514f648..a417cc1 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu glasnoću"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogući zvuk zvona unutar pojasne širine"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija AVRCP-a za Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Odaberite verziju AVRCP-a za Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek za Bluetooth Audio"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Prikazivat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su, primjerice, neprihvatljiva glasnoća ili nepostojanje kontrole."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogući reprodukciju melodija zvona telefona putem Bluetooth slušalica"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Omogući aplikaciju terminala koja nudi pristup lokalnoj ovojnici"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provjera"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 9c94579..b6f1460 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Név nélküli Bluetooth-eszközök megjelenítése"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Abszolút hangerő funkció letiltása"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Sávon belüli csörgetés engedélyezése"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"A Bluetooth AVRCP-verziója"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"A Bluetooth AVRCP-verziójának kiválasztása"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hang – Kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Az ADB/ADT útján telepített alkalmazások ellenőrzése kártékony viselkedésre."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Név nélküli Bluetooth-eszközök jelennek meg (csak MAC-címekkel)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Letiltja a Bluetooth abszolút hangerő funkcióját a távoli eszközökkel kapcsolatos hangerőproblémák – például elfogadhatatlanul magas vagy nem vezérelhető hangerő – esetén."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"A telefonon lévő csengőhangok Bluetooth-headseteken való lejátszásának engedélyezése"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Helyi végpont"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Végalkalmazás engedélyezése a helyi rendszerhéj eléréséhez"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ellenőrzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 80431a0..3ba3f45 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Ցուցադրել Bluetooth սարքերն առանց անունների"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Անջատել ձայնի բացարձակ ուժգնությունը"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Միացնել ներխմբային զանգը"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP տարբերակը"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Ընտրել Bluetooth AVRCP տարբերակը"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth աուդիո կոդեկ"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Ստուգեք տեղադրված հավելվածը ADB/ADT-ի միջոցով կասկածելի աշխատանքի պատճառով:"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth սարքերը կցուցադրվեն առանց անունների (միայն MAC հասցեները)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Կասեցնում է Bluetooth-ի ձայնի բացարձակ ուժգնության գործառույթը՝ հեռավոր սարքերի հետ ձայնի ուժգնությանը վերաբերող խնդիրներ ունենալու դեպքում (օրինակ՝ երբ ձայնի ուժգնությունն անընդունելի է կամ դրա կառավարումը հնարավոր չէ):"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Ընձեռել հեռախոսի բոլոր զանգերանգների Bluetooth ականջակալներով նվագարկումը"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Տեղային տերմինալ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Միացնել տերմինալային հավելվածը, որն առաջարկում է մուտք տեղային խեցի"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ստուգում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 536d22e..2bb9ae0 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Tampilkan perangkat Bluetooth tanpa nama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktifkan dering in-band"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pilih Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec Audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Periksa perilaku membahayakan dalam aplikasi yang terpasang melalui ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Perangkat Bluetooth tanpa nama (hanya alamat MAC) akan ditampilkan"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Menonaktifkan fitur volume absolut Bluetooth jika ada masalah volume dengan perangkat jarak jauh, misalnya volume terlalu keras atau kurangnya kontrol."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Izinkan nada dering di ponsel diputar di headset Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktifkan aplikasi terminal yang menawarkan akses kerangka lokal"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Pemeriksaan HDCP"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index a29fbe5..311227f 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Sýna Bluetooth-tæki án heita"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slökkva á samstillingu hljóðstyrks"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Leyfa símtöl á sömu rás"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-útgáfa"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Velja Bluetooth AVRCP-útgáfu"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hljóðkóðari"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kanna skaðlega hegðun forrita sem sett eru upp frá ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-tæki án heita (aðeins MAC-vistfang) verða birt"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slekkur á samstillingu Bluetooth-hljóðstyrks ef vandamál koma upp með hljóðstyrk hjá fjartengdum tækjum, svo sem of hár hljóðstyrkur eða erfiðleikar við stjórnun."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Leyfa að hringitónar í símanum spilist í Bluetooth-höfuðtólum"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Staðbundin skipanalína"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Virkja skipanalínuforrit sem leyfir staðbundinn skeljaraðgang"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-athugun"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index df0157a..b63232d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostra dispositivi Bluetooth senza nome"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disattiva volume assoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Attiva suoneria in banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versione Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Seleziona versione Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Verranno mostrati solo dispositivi Bluetooth senza nome (solo indirizzo MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Consente di disattivare la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Consenti la riproduzione delle suonerie del telefono tramite gli auricolari Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminale locale"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Abilita l\'app Terminale che offre l\'accesso alla shell locale"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verifica HDCP"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 0d78f26..538da91 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"הצגת מכשירי Bluetooth ללא שמות"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"השבת עוצמת קול מוחלטת"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"הפעל צלצולים בערוץ ה-Bluetooth (in-band ringing)"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth גרסה AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"בחר Bluetooth גרסה AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec אודיו ל-Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"בדוק אפליקציות שהותקנו באמצעות ADB/ADT לאיתור התנהגות מזיקה."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"יוצגו מכשירי Bluetooth ללא שמות (כתובות MAC בלבד)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"משבית את תכונת עוצמת הקול המוחלטת ב-Bluetooth במקרה של בעיות בעוצמת הקול במכשירים מרוחקים, כגון עוצמת קול רמה מדי או חוסר שליטה ברמת העוצמה."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"הפעלת רינגטונים באוזניות Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"מסוף מקומי"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"הפעל אפליקציית מסוף המציעה גישה מקומית למעטפת"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"בדיקת HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4dddcd7..db1baa1 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth デバイスを名前なしで表示"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"絶対音量を無効にする"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"インバンド リンギングを有効にする"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP バージョン"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP バージョンを選択する"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth オーディオ コーデック"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT経由でインストールされたアプリに不正な動作がないかを確認する"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth デバイスを名前なしで(MAC アドレスのみで)表示します"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"リモート端末で音量に関する問題(音量が大きすぎる、制御できないなど)が発生した場合に、Bluetooth の絶対音量の機能を無効にする。"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"スマートフォンの着信音が Bluetooth ヘッドセットで再生されることを許可する"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ローカルターミナル"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ローカルシェルアクセスを提供するターミナルアプリを有効にします"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCPチェック"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d202993..00eaf84 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-მოწყობილობების ჩვენება სახელების გარეშე"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ხმის აბსოლუტური სიძლიერის გათიშვა"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ზოლსშიდა დარეკვის ჩართვა"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-ის AVRCP-ის ვერსია"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"აირჩიეთ Bluetooth-ის AVRCP-ის ვერსია"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth აუდიოს კოდეკი"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"შეამოწმეთ, რამდენად უსაფრთხოა ADB/ADT-ის საშუალებით ინსტალირებული აპლიკაციები."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-მოწყობილობები ნაჩვენები იქნება სახელების გარეშე (მხოლოდ MAC-მისამართები)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"გათიშავს Bluetooth-ის ხმის აბსოლუტური სიძლიერის ფუნქციას დისტანციურ მოწყობილობებზე ხმასთან დაკავშირებული ისეთი პრობლემების არსებობის შემთხვევაში, როგორიცაა ხმის დაუშვებლად მაღალი სიძლიერე ან კონტროლის შეუძლებლობა."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ტელეფონის ზარების Bluetooth-ყურსაცვამებზე დაკვრის დაშვება"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ადგილობრივი ტერმინალი"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ლოკალურ გარსზე წვდომის ტერმინალური აპლიკაციის ჩართვა"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP შემოწმება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 9f7c166..a318bd8 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Атаусыз Bluetooth құрылғыларын көрсету"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ішкі жолақтағы шылдырлауды қосу"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP нұсқасы"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP нұсқасын таңдау"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудимазмұн кодегі"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT арқылы орнатылған қолданбалардың залалды болмауын тексеру."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Атаусыз Bluetooth құрылғылары (тек MAC мекенжайымен) көрсетіледі"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Қолайсыз қатты дыбыс деңгейі немесе басқарудың болмауы сияқты қашықтағы құрылғыларда дыбыс деңгейімен мәселелер жағдайында Bluetooth абсолютті дыбыс деңгейі функциясын өшіреді."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Телефондағы қоңырау әуендерінің Bluetooth құлақаспабында ойнатылуына мүмкіндік беру"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Жергілікті терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Жергілікті шелл-код қол жетімділігін ұсынатын терминалды қолданбаны қосу"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP (жоғары кең жолақты сандық мазмұнды қорғау) тексеру"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 59fca43..ae47318 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ការបង្កើនល្បឿនផ្នែករឹងសម្រាប់ការភ្ជាប់"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"បង្ហាញឧបករណ៍ប្ល៊ូធូសគ្មានឈ្មោះ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"បិទកម្រិតសំឡេងលឺខ្លាំង"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"បើកការរោទ៍ក្នុងបណ្តាញ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"កំណែប្ល៊ូធូស AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ជ្រើសរើសកំណែប្ល៊ូធូស AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"កូឌិកសំឡេងប៊្លូធូស"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ពិនិត្យកម្មវិធីបានដំឡើងតាមរយៈ ADB/ADT សម្រាប់ឥរិយាបថដែលគ្រោះថ្នាក់។"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ឧបករណ៍ប្ល៊ូធូសគ្មានឈ្មោះ (អាសយដ្ឋាន MAC តែប៉ុណ្ណោះ) នឹងបង្ហាញ"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"បិទលក្ខណៈពិសេសកម្រិតសំឡេងលឺខ្លាំងពេលភ្ជាប់ប៊្លូធូសក្នុងករណីមានបញ្ហាជាមួយឧបករណ៍បញ្ជាពីចម្ងាយ ដូចជាកម្រិតសំឡេងលឺខ្លាំងដែលមិនអាចទទួលយកបាន ឬខ្វះការគ្រប់គ្រង។"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"អនុញ្ញាតឲ្យសំឡេងរោទ៍នៅលើទូរសព្ទបញ្ចេញសំឡេងតាមរយៈកាសប្ល៊ូធូស"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ស្ថានីយមូលដ្ឋាន"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"បើកកម្មវិធីស្ថានីយដែលផ្ដល់ការចូលសែលមូលដ្ឋាន"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"ពិនិត្យ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 5a9bfb7..fbabb62 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್ವೇರ್ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ಹೆಸರುಗಳಿಲ್ಲದ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ಇನ್ ಬ್ಯಾಂಡ್ ರಿಂಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ಹಾನಿಮಾಡುವಂತಹ ವರ್ತನೆಗಾಗಿ ADB/ADT ಮೂಲಕ ಸ್ಥಾಪಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ಹೆಸರುಗಳಿಲ್ಲದ (ಕೇವಲ MAC ವಿಳಾಸಗಳು ಮಾತ್ರ) ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ರಿಮೋಟ್ ಸಾಧನಗಳೊಂದಿಗೆ ಒಪ್ಪಲಾಗದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್ ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ಫೋನ್ನ ರಿಂಗ್ಟೋನ್ಗಳನ್ನು ಬ್ಲೂಟೂತ್ ಹೆಡ್ಸೆಟ್ಗಳಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಅನುಮತಿ ನೀಡಿ"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index c198cb6..4b7d0a4 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"이름이 없는 블루투스 기기 표시"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"절대 볼륨 사용 안함"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"대역 내 벨소리 사용 설정"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"블루투스 AVRCP 버전"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"블루투스 AVRCP 버전 선택"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"블루투스 오디오 코덱"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT을 통해 설치된 앱에 유해한 동작이 있는지 확인"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"이름이 없이 MAC 주소만 있는 블루투스 기기가 표시됩니다."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"참기 어려울 정도로 볼륨이 크거나 제어가 되지 않는 등 원격 기기에서 볼륨 문제가 발생할 경우 블루투스 절대 볼륨 기능을 사용 중지합니다."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"휴대전화의 벨소리가 블루투스 헤드셋에서 재생되도록 허용"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"로컬 터미널"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"로컬 셸 액세스를 제공하는 터미널 앱 사용"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 확인"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 0e2b8c0..98ca36a 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Аталышсыз Bluetooth түзмөктөрү көрсөтүлсүн"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үндүн абсолюттук деңгээли өчүрүлсүн"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Канал аралык чалууну иштетүү"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP версиясы"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP версиясын тандоо"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT аркылуу орнотулган колдонмолорду зыянкечтикке текшерүү."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Аталышсыз Bluetooth түзмөктөрү (MAC даректери менен гана) көрсөтүлөт"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Алыскы түзмөктөр өтө катуу добуш чыгарып же көзөмөлдөнбөй жатса Bluetooth \"Үндүн абсолюттук деңгээли\" функциясын өчүрөт."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Телефондогу рингтондор Bluetooth гарнитурасында ойнотулсун"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Жергиликтүү терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Жергиликтүү буйрук кабыгын сунуштаган терминалга уруксат берүү"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP текшерүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 32a001b..6de2a2e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ສະແດງອຸປະກອນ Bluetooth ທີ່ບໍ່ມີຊື່"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ປິດໃຊ້ລະດັບສຽງສົມບູນ"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ເປີດສຽງເຕືອນແບບອິນແບນ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ເວີຊັນ Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ເລືອກເວີຊັນ Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ກວດສອບແອັບຯທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ຈະສະແດງອຸປະກອນ Bluetooth ທີ່ບໍ່ມີຊື່ (ທີ່ຢູ່ MAC ເທົ່ານັ້ນ)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ປິດໃຊ້ຄຸນສົມບັດລະດັບສຽງສົມບູນຂອງ Bluetooth ໃນກໍລະນີເກີດບັນຫາລະດັບສຽງສົມບູນກັບອຸປະກອນທາງໄກ ເຊັ່ນວ່າ ລະດັບສຽງດັງເກີນຍອມຮັບໄດ້ ຫຼື ຄວບຄຸມບໍ່ໄດ້."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ເປີດໃຫ້ສຽງຣິງໂທນຢູ່ໂທລະສັບດັງໃນຫູຟັງ Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal ໃນໂຕເຄື່ອງ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ເປີດນຳໃຊ້ແອັບຯ Terminal ທີ່ໃຫ້ການເຂົ້າເຖິງ shell ໃນໂຕເຄື່ອງໄດ້"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"ການກວດສອບ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 0e49f5be..66fa62a 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Rodyti „Bluetooth“ įrenginius be pavadinimų"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Išjungti didžiausią garsą"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Įgalinti diapazono skambėjimą"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"„Bluetooth“ AVRCP versija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pasirinkite „Bluetooth“ AVRCP versiją"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"„Bluetooth“ garso kodekas"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Patikrinkite, ar programų, įdiegtų naudojant ADB / ADT, veikimas nėra žalingas."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bus rodomi „Bluetooth“ įrenginiai be pavadinimų (tik MAC adresai)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Išjungiama „Bluetooth“ didžiausio garso funkcija, jei naudojant nuotolinio valdymo įrenginius kyla problemų dėl garso, pvz., garsas yra per didelis arba jo negalima tinkamai valdyti."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Leisti telefono skambėjimo tonus per „Bluetooth“ ausines"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Vietinis terminalas"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Įgal. terminalo progr., siūlančią prieigą prie viet. apvalkalo"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP tikrinimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index fd9d60c..f32accd 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Rādīt Bluetooth ierīces bez nosaukumiem"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Atspējot absolūto skaļumu"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Iespējot iekšjoslas zvanīšanu"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Atlasiet Bluetooth AVRCP versiju"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodeks"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Pārbaudīt, vai lietotņu, kuru instalēšanai izmantots ADB/ADT, darbība nav kaitīga."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Tiks parādītas Bluetooth ierīces bez nosaukumiem (tikai MAC adreses)."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Atspējo Bluetooth absolūtā skaļuma funkciju skaļuma problēmu gadījumiem attālajās ierīcēs, piemēram, ja ir nepieņemami liels skaļums vai nav iespējas kontrolēt skaļumu."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Atļaut tālrunī esošo zvana signālu atskaņošanu Bluetooth austiņās"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Vietējā beigu lietotne"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Iespējot beigu lietotni, kurā piedāvāta vietējā čaulas piekļuve"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP pārbaude"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 85cd020..3151f56 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Прикажувај уреди со Bluetooth без имиња"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Оневозможете апсолутна јачина на звук"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Овозможете ѕвонење во појас"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Изберете верзија Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодек за аудио преку Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Провери апликации инсталирани преку ADB/ADT за штетно однесување."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Уредите со Bluetooth без имиња (само MAC-адреси) ќе се прикажуваат"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ја оневозможува карактеристиката за апсолутна јачина на звук преку Bluetooth во случај кога ќе настанат проблеми со далечинските уреди, како на пр., неприфатливо силен звук или недоволна контрола."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дозволи мелодиите на телефонот да се пуштаат на Bluetooth слушалките"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Овозможи апликација на терминал што овозможува локален пристап кон школка."</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Проверување HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 77b58cf..2b86e50 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്വെയർ ത്വരിതപ്പെടുത്തൽ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"പേരില്ലാത്ത Bluetooth ഉപകരണങ്ങൾ കാണിക്കുക"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"അബ്സൊല്യൂട്ട് വോളിയം പ്രവർത്തനരഹിതമാക്കുക"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ഇൻ-ബാൻഡ് റിംഗുചെയ്യൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP പതിപ്പ്"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP പതിപ്പ് തിരഞ്ഞെടുക്കുക"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ഓഡിയോ കോഡെക്"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"കേടാക്കുന്ന പ്രവർത്തനരീതിയുള്ള ADB/ADT വഴി ഇൻസ്റ്റാളുചെയ്ത അപ്ലിക്കേഷനുകൾ പരിശോധിക്കുക."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"പേരില്ലാത്ത Bluetooth ഉപകരണങ്ങൾ (MAC വിലാസങ്ങൾ മാത്രം) പ്രദർശിപ്പിക്കും"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"അസ്വീകാര്യമായ തരത്തിൽ ഉയർന്ന വോളിയമോ ശബ്ദ നിയന്ത്രണത്തിന്റെ അഭാവമോ പോലെ, വിദൂര ഉപകരണങ്ങളുമായി ബന്ധപ്പെട്ട വോളിയം പ്രശ്നങ്ങൾ ഉണ്ടാകുന്ന സാഹചര്യത്തിൽ, Bluetooth അബ്സൊല്യൂട്ട് വോളിയം ഫീച്ചർ പ്രവർത്തനരഹിതമാക്കുന്നു."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ഫോണിലെ റിംഗ്ടോണുകൾ Bluetooth ഹെഡ്സെറ്റുകളിൽ പ്ലേ ചെയ്യാനായി അനുവദിക്കുക"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"പ്രാദേശിക ടെർമിനൽ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"പ്രാദേശിക ഷെൽ ആക്സസ് നൽകുന്ന ടെർമിനൽ അപ്ലിക്കേഷൻ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP പരിശോധന"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 3c6690c..152408a 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Нэргүй Bluetooth төхөөрөмжийг харуулах"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Сүлжээний хонхны аяыг идэвхжүүлэх"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP хувилбар"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP хувилбарыг сонгох"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодлогч"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT-р суулгасан апп-уудыг хорлонтой авиртай эсэхийг шалгах."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Нэргүй Bluetooth төхөөрөмжийг (зөвхөн MAC хаяг) харуулна"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Хэт чанга дуугаралт эсвэл муу тохиргоо зэрэг алсын зайн төхөөрөмжийн дуугаралттай холбоотой асуудлын үед Bluetooth-ийн үнэмлэхүй дууны түвшинг идэвхгүй болго."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Утасны хонхны аяыг Bluetooth чихэвчээр тоглуулахыг зөвшөөрөх"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локал терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Локал суурьт хандалт хийх боломж олгодог терминалын апп-г идэвхжүүлэх"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP шалгах"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index bb0a337..7402d29 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"नावांशिवाय ब्लूटूथ डिव्हाइस दाखवा"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"संपूर्ण आवाज अक्षम करा"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-बँड रिंगिंग सक्षम करा"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP आवृत्ती"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटूथ AVRCP आवृत्ती निवडा"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडिओ कोडेक"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे इंस्टॉल अॅप्स तपासा."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"नावांशिवाय ब्लूटूथ डीव्हाइस (फक्त MAC पत्ते) दाखवले जातील"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डीव्हाइसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटूथ संपूर्ण आवाज वैशिष्ट्य अक्षम करते."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फोनवरील रिंगटोन ब्लूटूथ हेडसेटवर वाजू द्या"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"स्थानिक टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"स्थानिक शेल प्रवेश देणारा टर्मिनल अॅप सक्षम करा"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP तपासणी"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index aa94b7c..51ab84e 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Tunjukkan peranti Bluetooth tanpa nama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Lumpuhkan kelantangan mutlak"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Dayakan dering dalam jalur"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pilih Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec Audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Semak apl yang dipasang melalui ADB/ADT untuk tingkah laku yang berbahaya."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Peranti Bluetooth tanpa nama (alamat MAC sahaja) akan dipaparkan"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Lumpuhkan ciri kelantangan mutlak Bluetooth dalam kes isu kelantangan menggunakan peranti kawalan jauh seperti kelantangan yang sangat kuat atau tidak dapat mengawal."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Benarkan nada dering pada telefon dimainkan pada set kepala Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal setempat"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Dayakan apl terminal yang menawarkan akses shell tempatan"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Penyemakan HDCP"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 57f6c6f..c643c59 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"အမည်မရှိသော ဘလူးတုသ်စက်ပစ္စည်းများကို ပြသရန်"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ပကတိ အသံနှုန်း သတ်မှတ်ချက် ပိတ်ရန်"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"သတ်မှတ်ထားသည့်ဖုန်းမြည်သံကို အသုံးပြုခြင်းအား ဖွင့်ရန်"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ဘလူးတုသ် AVRCP ဗားရှင်း"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ဘလူးတုသ် AVRCP ဗားရှင်းကို ရွေးပါ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT မှတဆင့် ထည့်သွင်းသော အပလီကေးရှင်းများကို အန္တရာယ်ဖြစ်နိုင်ခြင်း ရှိမရှိ စစ်ဆေးရန်။"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"အမည်မရှိသော (MAC လိပ်စာများသာပါသော) ဘလူးတုသ်စက်ပစ္စည်းများကို ပြသပါမည်"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ချိတ်ဆက်ထားသည့် ကိရိယာတွင် လက်မခံနိုင်လောက်အောင် ဆူညံ သို့မဟုတ် ထိန်းညှိမရနိုင်သော အသံပိုင်းပြဿနာ ရှိခဲ့လျှင် ဘလူးတုသ် ပကတိ အသံနှုန်းကို ပိတ်ပါ။"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ဖုန်းတွင်းရှိ ဖုန်းမြည်သံများကို ဘလူးတုသ် မိုက်ခွက်ပါနားကြပ်တွင် ဖွင့်ခွင့်ပြုရန်"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"လိုကယ်တာမီနယ်"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"local shell အသုံးပြုခွင့်ကမ်းလှမ်းသော တာမင်နယ်အပလီကေးရှင်းဖွင့်ပါ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP စစ်ဆေးမှု"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 1cabc5c..0cea1a7 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Vis Bluetooth-enheter uten navn"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slå av funksjonen for absolutt volum"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Slå på innenbåndsringing"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-versjon"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Velg Bluetooth AVRCP-versjon"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek for Bluetooth-lyd"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sjekk apper som er installert via ADB/ADT for skadelig adferd."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-enheter uten navn (bare MAC-adresser) vises"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillater at ringelyder på telefonen spilles av på Bluetooth-hodetelefoner"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktiver terminalappen som gir lokal kommandolistetilgang"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index f5f2269..d0ec0f5 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"नामकरण नगरिएका ब्लुटुथ यन्त्रहरू देखाउनुहोस्"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"निरपेक्ष आवाज असक्षम गर्नुहोस्"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-ब्यान्ड घन्टी बज्ने सुविधालाई सक्षम पार्नुहोस्"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लुटुथको AVRCP संस्करण"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लुटुथ अडियोको कोडेक"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक व्यवहारको लागि ADB/ADT को माध्यमबाट स्थापित अनुप्रयोगहरूको जाँच गर्नुहोस्।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"नामकरण नगरिएका ब्लुटुथ यन्त्रहरू (MAC ठेगाना भएका मात्र) देखाइनेछ"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"रिमोट यन्त्रहरूमा अस्वीकार्य चर्को आवाज वा नियन्त्रणमा कमी जस्ता आवाज सम्बन्धी समस्याहरूको अवस्थामा ब्लुटुथ निरपेक्ष आवाज सुविधालाई असक्षम गराउँछ।"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"उक्त फोनमा भएका रिङटोनहरूलाई ब्लुटुथका हेडसेटहरूमा प्ले गर्न दिनुहोस्"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल अनुप्रयोग सक्षम गर्नुहोस्"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP जाँच गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index fe17c1d..87d20c2 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-apparaten zonder namen weergeven"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Absoluut volume uitschakelen"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"In-band bellen inschakelen"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-AVRCP-versie"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth-AVRCP-versie selecteren"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-audiocodec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Apps die zijn geïnstalleerd via ADB/ADT, controleren op schadelijk gedrag"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-apparaten zonder namen (alleen MAC-adressen) worden weergegeven"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Hiermee wordt de functie voor absoluut volume van Bluetooth uitgeschakeld in geval van volumeproblemen met externe apparaten, zoals een onacceptabel hoog volume of geen volumeregeling."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Toestaan dat beltonen worden afgespeeld op Bluetooth-headsets"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokale terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Terminal-app inschakelen die lokale shell-toegang biedt"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-controle"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index c791107..d870a99 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਓ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ਪੂਰਨ ਵੌਲਿਊਮ ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ਇਨ-ਬੈਂਡ ਘੰਟੀ ਵੱਜਣ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ ਚੁਣੋ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਈਆਂ ਜਾਣਗੀਆਂ (ਸਿਰਫ਼ MAC ਪਤੇ)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਵੌਲਿਊਮ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਵੌਲਿਊਮ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਵੌਲਿਊਮ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਅਯੋਗ ਬਣਾਉਂਦਾ ਹੈ।"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਰਿੰਗਟੋਨਾਂ ਨੂੰ ਬਲੂਟੁੱਥ ਹੈੱਡਸੈੱਟਾਂ \'ਤੇ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"ਸਥਾਨਕ ਟਰਮੀਨਲ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"ਟਰਮੀਨਲ ਐਪ ਨੂੰ ਚਾਲੂ ਕਰੋ ਜੋ ਸਥਾਨਕ ਸ਼ੈਲ ਪਹੁੰਚ ਪੇਸ਼ਕਸ਼ ਕਰਦਾ ਹੈ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ਜਾਂਚ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3c0cf9e..7b66aa5 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Pokaż urządzenia Bluetooth bez nazw"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Wyłącz głośność bezwzględną"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Włącz dzwonek w kanale dźwiękowym"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Wersja AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Wybierz wersję AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek dźwięku Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sprawdź, czy aplikacje zainstalowane przez ADB/ADT nie zachowują się w szkodliwy sposób"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Zostaną wyświetlone urządzenia Bluetooth bez nazw (tylko adresy MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Wyłącza funkcję Głośność bezwzględna Bluetooth, jeśli występują problemy z urządzeniami zdalnymi, np. zbyt duża głośność lub brak kontroli."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Zezwala na odtwarzanie dzwonków telefonu w zestawach słuchawkowych Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokalny"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Włącz terminal, który umożliwia dostęp do powłoki lokalnej"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Sprawdzanie HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 240f850..d99097a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -142,7 +142,7 @@
<string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduzir uma rápida demonstração da voz sintetizada"</string>
<string name="tts_install_data_title" msgid="4264378440508149986">"Instalar dados de voz"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"É necessário instalar os dados de voz para a sintetização da fala"</string>
- <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Deseja ativar o uso desse mecanismo de síntese de fala?"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Quer ativar o uso desse mecanismo de síntese de fala?"</string>
<string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
<string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar o toque em banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no smartphone sejam reproduzidos em fones de ouvido Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 4852406af..8c7fbba 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar toque dentro da banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão de Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão de Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"São apresentados os dispositivos Bluetooth sem nomes (apenas endereços MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no telemóvel sejam reproduzidos em auscultadores com microfone integrado Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ativar aplicação terminal que oferece acesso local à shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 240f850..d99097a 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -142,7 +142,7 @@
<string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduzir uma rápida demonstração da voz sintetizada"</string>
<string name="tts_install_data_title" msgid="4264378440508149986">"Instalar dados de voz"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"É necessário instalar os dados de voz para a sintetização da fala"</string>
- <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Deseja ativar o uso desse mecanismo de síntese de fala?"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Quer ativar o uso desse mecanismo de síntese de fala?"</string>
<string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
<string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar o toque em banda"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no smartphone sejam reproduzidos em fones de ouvido Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 73869d50..1c67550 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afișați dispozitivele Bluetooth fără nume"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Dezactivați volumul absolut"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activați soneria în căști"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versiunea AVRCP pentru Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selectați versiunea AVRCP pentru Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Vor fi afișate dispozitivele Bluetooth fără nume (numai adresele MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permiteți ca tonurile de sonerie de pe telefon să fie redate prin căștile Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Aplicație terminal locală"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Activați aplicația terminal care oferă acces la shell local"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Verificare HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0ebf020..4b11594 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показывать Bluetooth-устройства без названий"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Включить внутриполосное воспроизведение"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выберите версию Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек для передачи через Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Выполнять проверку безопасности приложений при установке через ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Показывать Bluetooth-устройства без названий (только с MAC-адресами)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Отключить абсолютный уровень громкости Bluetooth при возникновении проблем на удаленных устройствах, например при слишком громком звучании или невозможности контролировать настройку."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Разрешить воспроизведение рингтонов на телефоне через Bluetooth-гарнитуру"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локальный терминальный доступ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Разрешить терминальный доступ к локальной оболочке"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Проверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 35631c9..2ffe814d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"නම් නොමැති බ්ලූටූත් උපාංග පෙන්වන්න"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"නිරපේක්ෂ හඩ පරිමාව අබල කරන්න"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"කලාපය තුළ නාද වීම සබල කරන්න"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"බ්ලූටූත් AVRCP අනුවාදය"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"බ්ලූටූත් AVRCP අනුවාදය තෝරන්න"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"බ්ලූටූත් ශ්රව්ය Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT හරහා ස්ථාපනය වූ යෙදුම්, විනාශකාරී ක්රියාවන් ඇත්දැයි පරික්ෂාකර බලන්න."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"නම් නොමැති බ්ලූටූත් උපාංග (MAC ලිපින පමණි) සංදර්ශනය කරනු ඇත"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"පිළිගත නොහැකි ලෙස වැඩි හඩ පරිමාව හෝ පාලනය නොමැති වීම යනාදී දුරස්ථ උපාංග සමගින් වන හඬ පරිමා ගැටලුවලදී බ්ලූටූත් නිරපේක්ෂ හඬ පරිමා විශේෂාංගය අබල කරයි."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"දුරකථනයේ නාද රටාවලට බ්ලූටූත් මත වාදනය වීමට ඉඩ දෙන්න"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"අභ්යන්තර අන්තය"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"දේශීය ෂෙල් ප්රවේශනය පිරිනමන ටර්මිනල් යෙදුම සබල කරන්න"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP පරික්ෂාව"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index c90e221..0cefd71 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Zobrazovať zariadenia Bluetooth bez názvov"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázať absolútnu hlasitosť"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Povoliť zvonenie v hovorovom pásme"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzia rozhrania Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Zvoľte verziu rozhrania Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio – kodek"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Zariadenia Bluetooth sa budú zobrazovať bez názvov (iba adresy MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou na vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Umožňuje prehrávať tóny zvonenia na telefóne v náhlavných súpravách Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Miestny terminál"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Povoliť terminálovú apl. na miestny prístup k prostrediu shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a131632..0864d5b 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Naprave Bluetooth prikaži brez imen"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogočanje absolutnega praga glasnosti"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogoči zvonjenje iz telefona"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Različica profila AVRCP za Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Izberite različico profila AVRCP za Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Zvočni kodek za Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Naprave Bluetooth bodo prikazane brez imen (samo z naslovi MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogoči funkcijo absolutnega praga glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogoči, da se toni zvonjenja v telefonu predvajajo v slušalkah z mikrofonom Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Omogočanje terminalske aplikacije za dostop do lokalne lupine"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Preverjanje HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index d5e92dc..63da6ff 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Shfaq pajisjet me Bluetooth pa emra"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Çaktivizo volumin absolut"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktivizo zilen brenda të njëjtit brez"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versioni AVRCP i Bluetooth-it"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Zgjidh versionin AVRCP të Bluetooth-it"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeku Bluetooth Audio"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollo aplikacionet e instaluara nëpërmjet ADB/ADT për sjellje të dëmshme."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Pajisjet me Bluetooth do të shfaqen pa emra (vetëm adresat MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Çaktivizon funksionin e volumit absolut të Bluetooth në rast të problemeve të volumit me pajisjet në largësi, si p.sh. një volum i lartë i papranueshëm ose mungesa e kontrollit."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Lejo që zilet në telefon të luhen në kufjet me \"Bluetooth\""</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Terminali lokal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktivizo aplikacionin terminal që ofron qasje në guaskën lokale"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrolli HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 94a1738..4c7aed8 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Прикажи Bluetooth уређаје без назива"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Онемогући главно подешавање јачине звука"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Омогућавање звоњаве на истом каналу"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP-а"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Изаберите верзију Bluetooth AVRCP-а"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверава да ли су апликације инсталиране преко ADB-а/ADT-а штетне."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Биће приказани Bluetooth уређаји без назива (само са MAC адресама)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Онемогућава главно подешавање јачине звука на Bluetooth уређају у случају проблема са јачином звука на даљинским уређајима, као што су изузетно велика јачина звука или недостатак контроле."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Омогућите да се мелодија звона на телефону пушта преко Bluetooth слушалица"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локални терминал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Омогући аплик. терминала за приступ локалном командном окружењу"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP провера"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 5a7dca3..e44dcd8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Visa namnlösa Bluetooth-enheter"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inaktivera Absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktivera samtal inom nätverket"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version för Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Välj AVRCP-version för Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Ljudkodek för Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollera om appar som installeras via ADB/ADT kan vara skadliga."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth-enheter utan namn (enbart MAC-adresser) visas"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inaktivera Bluetooth-funktionen Absolute volume om det skulle uppstå problem med volymen på fjärrenheter, t.ex. alldeles för hög volym eller brist på kontroll."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillåt att ringsignaler på mobilen kan spelas upp i Bluetooth-headset"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Aktivera en terminalapp som ger åtkomst till hyllor lokalt"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 01db36a..66cfda8 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Onyesha vifaa vya Bluetooth visivyo na majina"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zima sauti kamili"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Washa kipengele cha mlio wa simu katika kituo hicho hicho"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Toleo la Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Chagua Toleo la Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeki ya Sauti ya Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kagua programu zilizosakinishwa kupitia ADB/ADT kwa tabia ya kudhuru."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Itaonyesha vifaa vya Bluetooth bila majina (anwani za MAC pekee)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Huzima kipengele cha Bluetooth cha sauti kamili kunapotokea matatizo ya sauti katika vifaa vya mbali kama vile sauti ya juu mno au inaposhindikana kuidhibiti."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Ruhusu milio ya simu kwenye simu ichezwe kwenye Vifaa vya sauti vya Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Kituo cha karibu"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Washa programu ya mwisho inayotoa ufikiaji mkuu wa karibu"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Inakagua HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 71dcd0f..dd218c6 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"பெயர்கள் இல்லாத புளூடூத் சாதனங்களைக் காட்டு"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"இன்-பேண்ட் ரிங் செய்வதை இயக்கு"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"புளூடூத் AVRCP பதிப்பு"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"புளூடூத் AVRCP பதிப்பைத் தேர்ந்தெடு"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"புளூடூத் ஆடியோ கோடெக்"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"தீங்கு விளைவிக்கும் செயல்பாட்டை அறிய ADB/ADT மூலம் நிறுவப்பட்டப் பயன்பாடுகளைச் சரிபார்."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"பெயர்கள் இல்லாத புளூடூத் சாதனங்கள் (MAC முகவரிகள் மட்டும்) காட்டப்படும்"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"மிகவும் அதிகமான ஒலியளவு அல்லது கட்டுப்பாடு இழப்பு போன்ற தொலைநிலைச் சாதனங்களில் ஏற்படும் ஒலி தொடர்பான சிக்கல்கள் இருக்கும் சமயங்களில், புளூடூத் அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கும்."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ஃபோனில் இருக்கும் ரிங்டோன்களை, புளூடூத் ஹெட்செட்களில் இயக்க அனுமதி"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"அக முனையம்"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் பயன்பாட்டை இயக்கு"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP சரிபார்ப்பு"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 7db8e0d..b21eb8c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధి"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"పేర్లు లేని బ్లూటూత్ పరికరాలు చూపించు"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"సంపూర్ణ వాల్యూమ్ను నిలిపివేయి"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ఇన్-బ్యాండ్ రింగింగ్ని ప్రారంభించండి"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"బ్లూటూత్ AVRCP వెర్షన్"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"బ్లూటూత్ AVRCP సంస్కరణను ఎంచుకోండి"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"బ్లూటూత్ ఆడియో కోడెక్"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"హానికరమైన ప్రవర్తన కోసం ADB/ADT ద్వారా ఇన్స్టాల్ చేయబడిన అనువర్తనాలను తనిఖీ చేయి."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"పేర్లు (MAC చిరునామాలు మాత్రమే) లేని బ్లూటూత్ పరికరాలు ప్రదర్శించబడతాయి"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"రిమోట్ పరికరాల్లో ఆమోదించలేని స్థాయిలో అధిక వాల్యూమ్ ఉండటం లేదా వాల్యూమ్ నియంత్రణ లేకపోవడం వంటి సమస్యలు ఉంటే బ్లూటూత్ సంపూర్ణ వాల్యూమ్ లక్షణాన్ని నిలిపివేస్తుంది."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"బ్లూటూత్ హెడ్సెట్లలో ప్లే చేయడానికి ఫోన్లో రింగ్టోన్లను అనుమతించండి"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"స్థానిక టెర్మినల్"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"స్థానిక షెల్ ప్రాప్యతను అందించే టెర్మినల్ అనువర్తనాన్ని ప్రారంభించు"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP తనిఖీ"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index f2f1c90..447b188 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"แสดงอุปกรณ์บลูทูธที่ไม่มีชื่อ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"เปิดใช้การส่งเสียงในช่องสัญญาณเดียวกัน"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"เวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ตัวแปลงรหัสเสียงบลูทูธ"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ตรวจสอบแอปพลิเคชันที่ติดตั้งผ่าน ADB/ADT เพื่อตรวจดูพฤติกรรมที่เป็นอันตราย"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ระบบจะแสดงอุปกรณ์บลูทูธที่ไม่มีชื่อ (มีเฉพาะที่อยู่ MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ปิดใช้ฟีเจอร์การควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ให้เสียงเรียกเข้าในโทรศัพท์เล่นในชุดหูฟังบลูทูธ"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"เทอร์มินัลในตัวเครื่อง"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"เปิดใช้งานแอปเทอร์มินัลที่ให้การเข้าถึงเชลล์ในตัวเครื่อง"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"การตรวจสอบ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 871c384..a5e0b89 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Ipakita ang mga Bluetooth device na walang pangalan"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"I-disable ang absolute volume"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"I-enable ang pag-ring na nasa band"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bersyon ng AVRCP ng Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pumili ng Bersyon ng AVRCP ng Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tingnan kung may nakakahamak na pagkilos sa apps na na-install sa pamamagitan ng ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Ipapakita ang mga Bluetooth device na walang pangalan (mga MAC address lang)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dini-disable ang absolute volume feature ng Bluetooth kung may mga isyu sa volume ang mga malayong device gaya ng hindi katanggap-tanggap na malakas na volume o kawalan ng kontrol."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Payagan ang pag-play ng mga ringtone sa telepono sa mga headset na gumagamit ng Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal na terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Paganahin ang terminal app na nag-aalok ng lokal na shell access"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Pagsusuring HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 7b98d58..e6bba5b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Adsız Bluetooth cihazlarını göster"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mutlak sesi iptal et"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bant içi zil çaldırmayı etkinleştir"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Sürümü"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP Sürümünü seçin"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Ses Codec\'i"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT üzerinden yüklenen uygulamaları zararlı davranışlara karşı denetle."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Adsız Bluetooth cihazları (yalnızca MAC adresleri) gösterilecek"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzak cihazda sesin aşırı yüksek olması veya kontrol edilememesi gibi ses sorunları olması ihtimaline karşı Bluetooh mutlak ses özelliğini iptal eder."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Telefondaki zil seslerinin Bluetooth kulaklıklarda çalınmasına olanak tanır"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Yerel terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Yerel kabuk erişimi sunan terminal uygulamasını etkinleştir"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP denetimi"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 9514b2b..65f39ed 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показувати пристрої Bluetooth без назв"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Вимкнути абсолютну гучність"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Увімкнути внутрішньосмугові сигнали"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Виберіть версію Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодек для аудіо Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Перевіряти безпеку додатків, установлених через ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Пристрої Bluetooth відображатимуться без назв (лише MAC-адреси)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Функція абсолютної гучності Bluetooth вимикається, якщо на віддалених пристроях виникають проблеми, як-от надто висока гучність або втрата контролю."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дозволити відтворювати сигнали дзвінка на телефоні через гарнітуру Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Локальний термінал"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Увімк. програму-термінал, що надає локальний доступ до оболонки"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Перевірка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index a344c65..7830bb8 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ٹیدرنگ ہارڈویئر سرعت کاری"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"بغیر نام والے بلوٹوتھ آلات دکھائیں"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"مطلق والیوم کو غیر فعال کریں"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ان بینڈ رنگنگ فعال کریں"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"بلوٹوتھ AVRCP ورژن"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"بلوٹوتھ AVRCP ورژن منتخب کریں"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"بلوٹوتھ آڈیو کوڈیک"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"نقصان دہ رویے کے مدنظر ADB/ADT کی معرفت انسٹال شدہ ایپس کی جانچ کریں۔"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"بغیر نام والے بلوٹوتھ آلات (صرف MAC پتے) ڈسپلے کئے جائیں گے"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ریموٹ آلات کے ساتھ والیوم کے مسائل مثلاً نا قابل قبول حد تک بلند والیوم یا کنٹرول نہ ہونے کی صورت میں بلو ٹوتھ مطلق والیوم والی خصوصیت کو غیر فعال کریں۔"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"فون پر موجود رنگ ٹونز کو بلوٹوتھ ہیڈ سیٹز پر چلنے دیں"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"مقامی ٹرمینل"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"مقامی شیل رسائی پیش کرنے والی ٹرمینل ایپ فعال کریں"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP چیکنگ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index b222caf..acaaaf1 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth qurilmalarini nomlarisiz ko‘rsatish"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Ovoz balangligining mutlaq darajasini o‘chirib qo‘yish"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bitta liniyada jiringlashni yoqish"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versiyasi"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP versiyasini tanlang"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodeki"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT orqali o‘rnatilgan ilovalar xavfsizligini tekshiring"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Bluetooth qurilmalari nomsiz (faqat MAC manzillari) ko‘rsatiladi"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Masofadan ulanadigan qurilmalar bilan muammolar yuz berganda, jumladan, juda baland ovoz yoki sozlamalarni boshqarib bo‘lmaydigan holatlarda Bluetooth ovozi balandligining mutlaq darajasini o‘chirib qo‘yadi."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Bluetooth quloqliklarda ijro etish uchun telefonda ringtonlarga ruxsat bering"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Mahalliy terminal"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Mahalliy terminalga kirishga ruxsat beruvchi terminal ilovani faollashtirish"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP tekshiruvi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 64fbd93..7732b54 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Hiển thị các thiết bị Bluetooth không có tên"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Vô hiệu hóa âm lượng tuyệt đối"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bật đổ chuông trong dải"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth phiên bản AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Chọn Bluetooth phiên bản AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec âm thanh Bluetooth"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kiểm tra các ứng dụng được cài đặt qua ADB/ADT để xem có hoạt động gây hại hay không."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Các thiết bị Bluetooth không có tên (chỉ có địa chỉ MAC) sẽ được hiển thị"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Vô hiệu hóa tính năng âm lượng tuyệt đối qua Bluetooth trong trường hợp xảy ra sự cố về âm lượng với các thiết bị từ xa, chẳng hạn như âm lượng lớn không thể chấp nhận được hoặc thiếu kiểm soát."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Cho phép nhạc chuông trên điện thoại được phát trên tai nghe Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Dòng lệnh cục bộ"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Bật ứng dụng dòng lệnh cung cấp quyền truy cập vỏ cục bộ"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Kiểm tra HDCP"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 8029727..f036eae 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"显示没有名称的蓝牙设备"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用绝对音量功能"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"启用手机默认铃声"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"蓝牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"选择蓝牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"蓝牙音频编解码器"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"通过 ADB/ADT 检查安装的应用是否存在有害行为。"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"系统将显示没有名称(只有 MAC 地址)的蓝牙设备"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"停用蓝牙绝对音量功能,即可避免在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允许手机铃声通过蓝牙耳机播放"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"本地终端"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"启用终端应用,以便在本地访问 Shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 检查"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index dcec71f..d57a8fd 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"顯示沒有名稱的藍牙裝置"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"啟用頻內鈴聲"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"選擇藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"藍牙音訊編解碼器"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"透過 ADB/ADT 檢查安裝的應用程式有否有害的行為。"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"系統將顯示沒有名稱 (只有 MAC 位址) 的藍牙裝置"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"連線至遠端裝置時,如發生音量過大或無法控制音量等問題,請停用藍牙絕對音量功能。"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允許藍牙耳機播放手機鈴聲"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 檢查"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 28def2d..5a329fa 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"顯示沒有名稱的藍牙裝置"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"啟用藍牙同步鈴聲功能"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"選取藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"藍牙音訊轉碼器"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"檢查透過 ADB/ADT 安裝的應用程式是否具有有害行為。"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"系統會顯示沒有名稱 (僅具有 MAC 位址) 的藍牙裝置"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"只要停用藍牙絕對音量功能,即可避免在連線到遠端裝置時,發生音量過大或無法控制音量等問題。"</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允許手機鈴聲透過藍牙耳機播放"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 檢查"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 337bd57..3649ba2 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -202,7 +202,6 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bonisa amadivayisi e-Bluetooth ngaphandle kwamagama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Khubaza ivolumu ngokuphelele"</string>
- <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Nika amandla ukukhala okuphakathi nomkhiqizo"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Inguqulo ye-Bluetooth ye-AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Khetha inguqulo ye-Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"I-Bluetooth Audio Codec"</string>
@@ -248,7 +247,6 @@
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Hlola izinhlelo zokusebenza ezifakiwe nge-ADB/ADT ngokuziphatha okuyingozi."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"Amadivayisi e-Bluetooth anganawo amagama (Amakheli e-MAC kuphela) azoboniswa"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ikhubaza isici esiphelele sevolumu ye-Bluetooth uma kuba nezinkinga zevolumu ngamadivayisi esilawuli kude ezifana nevolumu ephezulu noma eshoda ngokulawuleka."</string>
- <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Vumela amathoni okukhala efonini ukuthi adlalwe kuma-earphone e-Bluetooth"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Itheminali yasendaweni"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"Nika amandla uhlelo lokusebenza letheminali olunikeza ukufinyelela kwasendaweni kwe-shell"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"Ihlola i-HDCP"</string>
diff --git a/packages/SettingsLib/res/values/styles_support_preference.xml b/packages/SettingsLib/res/values/styles_support_preference.xml
index cf9f3c6..59de6c9 100644
--- a/packages/SettingsLib/res/values/styles_support_preference.xml
+++ b/packages/SettingsLib/res/values/styles_support_preference.xml
@@ -66,6 +66,14 @@
<item name="singleLineTitle">false</item>
</style>
+ <!-- CheckBox Preferences -->
+ <style name="Preference.CheckBoxPreference.SettingsBase" parent="@style/Preference.CheckBoxPreference.Material">
+ <item name="allowDividerAbove">false</item>
+ <item name="allowDividerBelow">true</item>
+ <item name="iconSpaceReserved">true</item>
+ <item name="singleLineTitle">false</item>
+ </style>
+
<!-- EditText Preferences -->
<style name="Preference.EditTextPreference.SettingsBase"
parent="@style/Preference.DialogPreference.EditTextPreference.Material">
@@ -86,6 +94,7 @@
<item name="editTextPreferenceStyle">@style/Preference.EditTextPreference.SettingsBase</item>
<item name="footerPreferenceStyle">@style/Preference.FooterPreference.SettingsBase</item>
<item name="switchPreferenceStyle">@style/Preference.SwitchPreference.SettingsBase</item>
+ <item name="checkBoxPreferenceStyle">@style/Preference.CheckBoxPreference.SettingsBase</item>
<item name="dropdownPreferenceStyle">@style/Preference.DropdownPreference.SettingsBase</item>
</style>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 0d67ad0..e8f5282 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -51,10 +51,7 @@
connected = networkInfo != null && networkInfo.isConnected();
// If Connected grab the signal strength and ssid.
if (connected) {
- // try getting it out of the intent first
- WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
- ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
- : mWifiManager.getConnectionInfo();
+ WifiInfo info = mWifiManager.getConnectionInfo();
if (info != null) {
ssid = getSsid(info);
} else {
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 02a4973..7cf7163 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -49,7 +49,7 @@
LOCAL_JAVA_LIBRARIES := \
junit \
- platform-robolectric-3.5.1-prebuilt
+ platform-robolectric-3.6.1-prebuilt
LOCAL_INSTRUMENTATION_FOR := SettingsLibShell
LOCAL_MODULE := SettingsLibRoboTests
@@ -74,4 +74,4 @@
LOCAL_ROBOTEST_TIMEOUT := 36000
-include prebuilts/misc/common/robolectric/3.5.1/run_robotests.mk
+include prebuilts/misc/common/robolectric/3.6.1/run_robotests.mk
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index f1fb208..ae88227 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -288,65 +288,9 @@
@Override
public void onFullBackup(FullBackupDataOutput data) throws IOException {
- byte[] systemSettingsData = getSystemSettings();
- byte[] secureSettingsData = getSecureSettings();
- byte[] globalSettingsData = getGlobalSettings();
- byte[] lockSettingsData = getLockSettings(UserHandle.myUserId());
- byte[] locale = mSettingsHelper.getLocaleData();
- byte[] softApConfigData = getSoftAPConfiguration();
- byte[] netPoliciesData = getNetworkPolicies();
- byte[] wifiFullConfigData = getNewWifiConfigData();
-
- // Write the data to the staging file, then emit that as our tarfile
- // representation of the backed-up settings.
- String root = getFilesDir().getAbsolutePath();
- File stage = new File(root, STAGE_FILE);
- try {
- FileOutputStream filestream = new FileOutputStream(stage);
- BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
- DataOutputStream out = new DataOutputStream(bufstream);
-
- if (DEBUG_BACKUP) Log.d(TAG, "Writing flattened data version " + FULL_BACKUP_VERSION);
- out.writeInt(FULL_BACKUP_VERSION);
-
- if (DEBUG_BACKUP) Log.d(TAG, systemSettingsData.length + " bytes of settings data");
- out.writeInt(systemSettingsData.length);
- out.write(systemSettingsData);
- if (DEBUG_BACKUP) {
- Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
- }
- out.writeInt(secureSettingsData.length);
- out.write(secureSettingsData);
- if (DEBUG_BACKUP) {
- Log.d(TAG, globalSettingsData.length + " bytes of global settings data");
- }
- out.writeInt(globalSettingsData.length);
- out.write(globalSettingsData);
- if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data");
- out.writeInt(locale.length);
- out.write(locale);
- if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
- out.writeInt(lockSettingsData.length);
- out.write(lockSettingsData);
- if (DEBUG_BACKUP) Log.d(TAG, softApConfigData.length + " bytes of softap config data");
- out.writeInt(softApConfigData.length);
- out.write(softApConfigData);
- if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of net policies data");
- out.writeInt(netPoliciesData.length);
- out.write(netPoliciesData);
- if (DEBUG_BACKUP) {
- Log.d(TAG, wifiFullConfigData.length + " bytes of wifi config data");
- }
- out.writeInt(wifiFullConfigData.length);
- out.write(wifiFullConfigData);
-
- out.flush(); // also flushes downstream
-
- // now we're set to emit the tar stream
- fullBackupFile(stage, data);
- } finally {
- stage.delete();
- }
+ // Full backup of SettingsBackupAgent support was removed in Android P. If you want to adb
+ // backup com.android.providers.settings package use \"-keyvalue\" flag.
+ // Full restore of SettingsBackupAgent is still available for backwards compatibility.
}
@Override
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 1d3f26ee..48de1c9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1720,9 +1720,6 @@
Settings.Secure.QS_TILES,
SecureSettingsProto.QS_TILES);
dumpSetting(s, p,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE,
- SecureSettingsProto.DEMO_USER_SETUP_COMPLETE);
- dumpSetting(s, p,
Settings.Secure.INSTANT_APPS_ENABLED,
SecureSettingsProto.INSTANT_APPS_ENABLED);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index bef2bcb..1167d69 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2592,7 +2592,9 @@
public void onUidRemovedLocked(int uid) {
final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID,
UserHandle.getUserId(uid));
- ssaidSettings.deleteSettingLocked(Integer.toString(uid));
+ if (ssaidSettings != null) {
+ ssaidSettings.deleteSettingLocked(Integer.toString(uid));
+ }
}
@Nullable
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d675a7a..b3d6357 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -43,6 +43,7 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.MANAGE_USB" />
+ <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
<!-- System tool permissions granted to the shell. -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 29ecac0..aa2cdbb 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -49,6 +49,7 @@
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
+ <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index b154d46..5e09e75 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -32,6 +32,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/widget_vertical_padding"
+ android:paddingStart="64dp"
+ android:paddingEnd="64dp"
android:theme="@style/TextAppearance.Keyguard"
/>
<LinearLayout android:id="@+id/row"
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 7027d6f..b3ed8f5 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -101,7 +101,7 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"رمز \"رقم التعريف الشخصي\" لشريحة SIM غير صحيح، ويلزمك الاتصال الآن بمشغّل شبكة الجوّال لإلغاء قفل الجهاز."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
- <item quantity="zero">رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ولم تتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
+ <item quantity="zero">رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ولم تتبق لديك أي محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
<item quantity="two">رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ويتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
<item quantity="few">رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات.</item>
<item quantity="many">رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة.</item>
@@ -110,7 +110,7 @@
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"شريحة SIM غير صالحة للاستخدام. يُرجى الاتصال بمشغّل شبكة الجوّال."</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
- <item quantity="zero">رمز PUK لشريحة SIM غير صحيح، ولم تتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="zero">رمز PUK لشريحة SIM غير صحيح، ولم تتبق لديك أي محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
<item quantity="two">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
<item quantity="few">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
<item quantity="many">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index b74a618..1f6addf 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -147,8 +147,8 @@
<item quantity="other">Unesite PIN kôd za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
- <item quantity="one">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item>
- <item quantity="few">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item>
- <item quantity="other">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Obratite se operateru za više informacija.</item>
+ <item quantity="one">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva. Za više informacija kontaktirajte mobilnog operatera.</item>
+ <item quantity="few">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Za više informacija kontaktirajte mobilnog operatera.</item>
+ <item quantity="other">SIM kartica je onemogućena. Unesite PUK kôd da nastavite. Imate još <xliff:g id="_NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva. Za više informacija kontaktirajte mobilnog operatera.</item>
</plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index e511940..b6dc72b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -135,4 +135,12 @@
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"Not recognised"</string>
+ <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
+ <item quantity="other">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
+ <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
+ <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
+ <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index e511940..b6dc72b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -135,4 +135,12 @@
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"Not recognised"</string>
+ <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
+ <item quantity="other">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
+ <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
+ <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
+ <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index e511940..b6dc72b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -135,4 +135,12 @@
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"Not recognised"</string>
+ <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
+ <item quantity="other">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
+ <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
+ <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
+ <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index e511940..b6dc72b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -135,4 +135,12 @@
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"Not recognised"</string>
+ <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
+ <item quantity="other">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
+ <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
+ <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact operator for details.</item>
+ <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact operator for details.</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index dede142..97d16c6 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -135,4 +135,12 @@
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"Not recognized"</string>
+ <plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
+ <item quantity="other">Enter SIM PIN, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Enter SIM PIN, you have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item>
+ </plurals>
+ <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
+ <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
+ <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact carrier for details.</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 001f90c..813377a 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -140,7 +140,7 @@
<item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
- <item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Contatta l\'operatore per avere informazioni dettagliate.</item>
- <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Contatta l\'operatore per avere informazioni dettagliate.</item>
+ <item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
+ <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
</plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 6534fbb..fb85589 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -136,11 +136,11 @@
</plurals>
<string name="fingerprint_not_recognized" msgid="348813995267914625">"မသိပါ"</string>
<plurals name="kg_password_default_pin_message" formatted="false" msgid="6203676909479972943">
- <item quantity="other">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item>
- <item quantity="one">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်စက်ကို ဖွင့်ရန် ဝန်ဆောင်မှုပေးသူသို့ မဆက်သွယ်မီ သင့်တွင် <xliff:g id="NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item>
+ <item quantity="other">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။</item>
+ <item quantity="one">ဆင်းမ်ကဒ် ပင်နံပါတ် ထည့်သွင်းပါ၊ သင့်စက်ကို လော့ခ်ဖွင့်ပေးရန်အတွက် ဝန်ဆောင်မှုပေးသူသို့ မဆက်သွယ်မီ <xliff:g id="NUMBER_0">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။</item>
</plurals>
<plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
- <item quantity="other">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ်ကို အပြီးသုံးမရအောင်မပြုမီ သင့်တွင် <xliff:g id="_NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့်ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
- <item quantity="one">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ်ကို အပြီးသုံးမရအောင်မပြုမီ သင့်တွင် <xliff:g id="_NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့်ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
+ <item quantity="other">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် PUK ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ် အပြီးပိတ်မသွားမီ သင့်တွင် <xliff:g id="_NUMBER_1">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
+ <item quantity="one">ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် PUK ကုဒ်ကို ထည့်ပါ။ ဆင်းမ်ကဒ် အပြီးပိတ်မသွားမီ သင့်တွင် <xliff:g id="_NUMBER_0">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့် ကျန်ပါသေးသည်။ အသေးစိတ်အချက်များအတွက် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ။</item>
</plurals>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 85e0a95..6aa66dd 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -50,7 +50,7 @@
<string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"Gebied voor pincode"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Gebied voor pincode van simkaart"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Gebied voor pukcode van simkaart"</string>
- <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Volgende alarm ingesteld voor <xliff:g id="ALARM">%1$s</xliff:g>"</string>
+ <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Volgende wekker ingesteld voor <xliff:g id="ALARM">%1$s</xliff:g>"</string>
<string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Delete"</string>
<string name="disable_carrier_button_text" msgid="6914341927421916114">"Simkaart uitschakelen"</string>
<string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 463af61..04cf6b0 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -57,7 +57,7 @@
<dimen name="widget_separator_thickness">2dp</dimen>
<dimen name="widget_horizontal_padding">8dp</dimen>
<dimen name="widget_icon_size">16dp</dimen>
- <dimen name="widget_icon_padding">4dp</dimen>
+ <dimen name="widget_icon_padding">8dp</dimen>
<!-- The y translation to apply at the start in appear animations. -->
<dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index d50bab5..5f52e2a 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -83,13 +83,13 @@
<item name="android:gravity">center</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyLight</item>
</style>
<style name="TextAppearance.Keyguard.Secondary">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">@dimen/widget_label_font_size</item>
- <item name="android:singleLine">true</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
new file mode 100644
index 0000000..1eb4004
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_info.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,34h4L26,22h-4v12zM24,4C12.95,4 4,12.95 4,24s8.95,20 20,20 20,-8.95 20,-20S35.05,4 24,4zM24,40c-8.82,0 -16,-7.18 -16,-16S15.18,8 24,8s16,7.18 16,16 -7.18,16 -16,16zM22,18h4v-4h-4v4z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 2e35d86..6b5bd12 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -23,23 +23,22 @@
android:clickable="true"
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
+ android:paddingEnd="@*android:dimen/notification_content_margin_end"
android:background="@color/notification_guts_bg_color"
android:theme="@*android:style/Theme.DeviceDefault.Light">
<!-- Package Info -->
- <LinearLayout
+ <RelativeLayout
android:layout_width="match_parent"
- android:layout_height="@*android:dimen/notification_header_height"
+ android:layout_height="@dimen/notification_guts_header_height"
android:clipChildren="false"
- android:paddingTop="@*android:dimen/notification_header_padding_top"
- android:paddingBottom="@*android:dimen/notification_header_padding_bottom"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
+ android:clipToPadding="false"
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top" >
<ImageView
android:id="@+id/pkgicon"
- android:layout_width="@*android:dimen/notification_header_icon_size"
- android:layout_height="@*android:dimen/notification_header_icon_size"
- android:layout_marginEnd="3dp"/>
+ android:layout_width="@dimen/notification_guts_header_height"
+ android:layout_height="@dimen/notification_guts_header_height"
+ android:layout_marginEnd="3dp" />
<TextView
android:id="@+id/pkgname"
android:layout_width="wrap_content"
@@ -47,7 +46,9 @@
android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
android:layout_marginStart="3dp"
android:layout_marginEnd="2dp"
- android:singleLine="true"/>
+ android:singleLine="true"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/pkgicon" />
<TextView
android:id="@+id/pkg_group_divider"
android:layout_width="wrap_content"
@@ -55,7 +56,9 @@
android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
- android:text="@*android:string/notification_header_divider_symbol"/>
+ android:text="@*android:string/notification_header_divider_symbol"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/pkgname" />
<TextView
android:id="@+id/group_name"
android:layout_width="wrap_content"
@@ -64,82 +67,103 @@
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:ellipsize="end"
- android:maxLines="1"/>
- </LinearLayout>
+ android:maxLines="1"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/pkg_group_divider" />
+ <ImageButton
+ android:id="@+id/info"
+ android:src="@drawable/ic_info"
+ android:tint="?android:attr/colorAccent"
+ android:layout_width="@dimen/notification_guts_header_height"
+ android:layout_height="@dimen/notification_guts_header_height"
+ android:contentDescription="@string/notification_more_settings"
+ android:background="@drawable/ripple_drawable"
+ android:layout_alignParentEnd="true" />
+ </RelativeLayout>
- <!-- Channel Info Block -->
<LinearLayout
+ android:id="@+id/prompt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="20dp"
- android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+ android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top"
android:orientation="vertical">
- <!-- Channel Text -->
+
+ <!-- Channel Info Block -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:orientation="vertical">
<!-- Channel Name -->
<TextView
android:id="@+id/channel_name"
- android:layout_width="0dp"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginBottom="6dp"
style="@style/TextAppearance.NotificationInfo.Primary" />
- <!-- Ban Channel Switch -->
- <Switch
- android:id="@+id/channel_enabled_switch"
+ <!-- Question prompt -->
+ <TextView
+ android:id="@+id/block_prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="end|center_vertical"
- android:contentDescription="@string/notification_channel_switch_accessibility"
- android:background="@null" />
+ style="@style/TextAppearance.NotificationInfo.Secondary" />
</LinearLayout>
- <!-- Secondary Text - only one shows at a time -->
- <TextView
- android:id="@+id/channel_disabled"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/notification_channel_disabled"
- style="@style/TextAppearance.NotificationInfo.Secondary.Warning" />
- <TextView
- android:id="@+id/num_channels_desc"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/notification_channel_disabled"
- style="@style/TextAppearance.NotificationInfo.Secondary" />
- <!-- Optional link to app. Only appears if the channel is not disabled -->
- <TextView
- android:id="@+id/app_settings"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:ellipsize="end"
- android:maxLines="1"
- style="@style/TextAppearance.NotificationInfo.Secondary.Link"/>
- </LinearLayout>
- <!-- Settings and Done buttons -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:orientation="horizontal"
- android:gravity="end"
- android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
- android:layout_marginBottom="8dp" >
- <TextView
- android:id="@+id/more_settings"
- android:text="@string/notification_more_settings"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginEnd="8dp"
- style="@style/TextAppearance.NotificationInfo.Button"/>
- <TextView
- android:id="@+id/done"
- android:text="@string/notification_done"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- style="@style/TextAppearance.NotificationInfo.Button"/>
+ <!-- Settings and Done buttons -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/notification_guts_button_spacing"
+ android:gravity="end" >
+
+ <!-- Optional link to app. Only appears if the channel is not disabled and the app
+ asked for it -->
+ <TextView
+ android:id="@+id/app_settings"
+ android:text="@string/notification_app_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:ellipsize="end"
+ android:maxLines="1"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/block"
+ android:text="@string/inline_stop_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/keep"
+ android:text="@string/inline_keep_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="-8dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </LinearLayout>
</LinearLayout>
+ <RelativeLayout
+ android:id="@+id/confirmation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top"
+ android:visibility="gone"
+ android:orientation="horizontal" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notification_channel_disabled"
+ style="@style/TextAppearance.NotificationInfo.Secondary.Warning"/>
+ <TextView
+ android:id="@+id/undo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inline_undo"
+ android:layout_alignParentEnd="true"
+ android:layout_marginEnd="-8dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </RelativeLayout>
</com.android.systemui.statusbar.NotificationInfo>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 15a7d4c..fb756e3 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tik om te demp."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volumekontroles word gewys. Swiep na bo om toe te maak."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volumekontroles is versteek"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media-uitvoer"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Foonoproep-uitvoer"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Geen toestelle gekry nie"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Geen toestelle gekry nie. Probeer om <xliff:g id="SERVICE">%1$s</xliff:g> aan te skakel"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth en Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Stelsel-UI-ontvanger"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Wys persentasie van ingebedde battery"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Wys batteryvlakpersentasie binne die statusbalkikoon wanneer dit nie laai nie"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Vou uit"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeer"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Maak toe"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep af om toe te maak"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Kieslys"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index ee9acae..077131c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ።"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"የ%s ድምጽ መቆጣጠሪያዎች ይታያሉ። ለማሰናበት ወደ ላይ ያንሸራትቱ።"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"የድምጽ መቆጣጠሪያዎች ተደብቀዋል"</string>
+ <string name="output_title" msgid="5355078100792942802">"የሚዲያ ውጽዓት"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"የስልክ ጥሪ ውፅዓት"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ምንም መሣሪያዎች አልተገኙም"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ምንም መሣሪያዎች አልተገኙም። <xliff:g id="SERVICE">%1$s</xliff:g>ን ማብራት ይሞክሩ።"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ብሉቱዝ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ብሉቱዝ እና Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"የስርዓት በይነገጽ መቃኛ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"የተቀላቀለ የባትሪ አጠቃቀም መቶኛ አሳይ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ኃይል በማይሞላበት ጊዜ በሁነታ አሞሌ አዶ ውስጥ የባትሪ ደረጃ መቶኛን አሳይ"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ዝጋ"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ለማሰናበት ወደ ታች ይጎትቱ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"ምናሌ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1d8cb4e..e5db8de 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -26,7 +26,7 @@
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"تظهر شاشاتك المعروضة مؤخرًا هنا"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"إزالة التطبيقات الحديثة"</string>
<plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
- <item quantity="zero"> لا توجد أية شاشات (%d) في النظرة العامة</item>
+ <item quantity="zero"> لا توجد أي شاشات (%d) في النظرة العامة</item>
<item quantity="two">شاشتان (%d) في النظرة العامة</item>
<item quantity="few">%d شاشات في النظرة العامة</item>
<item quantity="many">%d شاشة في النظرة العامة</item>
@@ -302,7 +302,7 @@
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"إيقاف Wi-Fi"</string>
<string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"تم تشغيل Wi-Fi"</string>
- <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"لا تتوفر أية شبكة Wi-Fi"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"لا تتوفر أي شبكة Wi-Fi"</string>
<string name="quick_settings_cast_title" msgid="7709016546426454729">"إرسال"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"جارٍ الإرسال"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"جهاز لا يحمل اسمًا"</string>
@@ -511,6 +511,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. انقر لكتم الصوت."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"تم عرض %s عنصر تحكم في مستوى الصوت. يمكنك التمرير سريعًا لأعلى للتجاهل."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"تم إخفاء عناصر التحكم في مستوى الصوت"</string>
+ <string name="output_title" msgid="5355078100792942802">"إخراج الوسائط"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"إخراج المكالمة الهاتفية"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"لم يتم العثور على أي أجهزة."</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"لم يتم العثور على أي أجهزة. جرِّب تفعيل <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"البلوتوث"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"البلوتوث وWi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"أداة ضبط واجهة مستخدم النظام"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"عرض نسبة البطارية المدمجة"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"عرض نسبة مستوى البطارية داخل رمز شريط الحالة أثناء عدم الشحن"</string>
@@ -748,6 +755,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"إغلاق"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"اسحب لأسفل للإلغاء"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"القائمة"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 098b1cd..1b2972b 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Çoxsaylı ton olan ikili tezlik"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Münasiblik"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Zənglər"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zəng"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrasiya"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Susdurun"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Səssiz etmək üçün klikləyin."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s həcm nəzarəti göstərilir. Bitirmək üçün yuxarı çəkin."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Həcm nəzarət gizlədilib"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media çıxışı"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Zəng girişi"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Heç bir cihaz tapılmadı"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Cihaz tapılmadı. <xliff:g id="SERVICE">%1$s</xliff:g> xidmətini aktiv edin"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth və Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Daxil batareya faizini göstərin"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Elektrik şəbəsinə qoşulu olmayan zaman batareya səviyyəsini status paneli ikonası daxilində göstərin"</string>
@@ -723,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Bağlayın"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Rədd etmək üçün aşağı çəkin"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index fd42eb5..2d3635c 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dodirnite da biste isključili zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Kontrole za jačinu zvuka (%s) su prikazane. Prevucite nagore da biste ih odbacili."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrole za jačinu zvuka su sakrivene"</string>
+ <string name="output_title" msgid="5355078100792942802">"Izlaz medija"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Izlaz za telefonski poziv"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nije pronađen nijedan uređaj"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nije pronađen nijedan uređaj. Probajte da uključite uslugu <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth i Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tjuner za korisnički interfejs sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikazuj ugrađeni procenat baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazivanje nivoa napunjenosti baterije u procentima unutar ikone na statusnoj traci kada se baterija ne puni"</string>
@@ -730,6 +737,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Prevucite nadole da biste odbili"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index e82dbff..27e3a7d 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -509,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Дакраніцеся, каб адключыць гук"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Паказваецца наступная колькасць рэгулятараў гучнасці: %s. Правядзіце пальцам уверх, каб закрыць іх."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Рэгулятары гучнасці схаваны"</string>
+ <string name="output_title" msgid="5355078100792942802">"Вывад мультымедыя"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Прылада вываду тэлефонных выклікаў"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Прылады не знойдзены"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Прылады не знойдзены. Паспрабуйце ўключыць <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth і Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Наладка сістэмнага інтэрфейсу карыстальніка"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Паказваць працэнт зараду акумулятара"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Паказваць працэнт узроўню акумулятара ўнутры значка панэлі стану, калі ён не зараджаецца"</string>
@@ -738,6 +745,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Закрыць"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перацягніце ўніз, каб адхіліць"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ccdc44b..6a93d9e 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Докоснете, за да заглушите звука."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Показани са контролите за силата на звука на %s. Прекарайте пръст нагоре, за да ги скриете."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Контролите за силата на звука са скрити"</string>
+ <string name="output_title" msgid="5355078100792942802">"Изходяща мултимедия"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Изходящи телефонни обаждания"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Няма намерени устройства"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Няма намерени устройства. Включете <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth и Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Тунер на системния потребителски интерфейс"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показване на процента на вградената батерия"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Показване на процента на нивото на батерията в иконата на лентата на състоянието, когато не се зарежда"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Затваряне"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Преместете надолу с плъзгане, за да отхвърлите"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 96028f7..4b163ec 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ব্লুটুথ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ডুয়েল মাল্টি টোন ফ্রিকোয়েন্সি"</string>
<string name="stream_accessibility" msgid="301136219144385106">"অ্যাক্সেসযোগ্যতা"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"কল"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"রিং"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ভাইব্রেট"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"মিউট"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। নিঃশব্দ করতে ট্যাপ করুন।"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ভলিউম নিয়ন্ত্রণগুলি দেখানো হয়েছে৷ খারিজ করতে উপরের দিকে সোয়াইপ করুন৷"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ভলিউম নিয়ন্ত্রণগুলি লুকানো রয়েছে"</string>
+ <string name="output_title" msgid="5355078100792942802">"মিডিয়া আউটপুট"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ফোন কল আউটপুট"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"কোনও ডিভাইস খুঁজে পাওয়া যায়নি"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"কোনও ডিভাইস খুঁজে পাওয়া যায়নি। <xliff:g id="SERVICE">%1$s</xliff:g> চালু করার চেষ্টা করুন"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ব্লুটুথ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"ওয়াই-ফাই"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ব্লুটুথ এবং ওয়াই-ফাই"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"সিস্টেম UI টিউনার"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"এম্বেড করা ব্যাটারির শতকরা হার দেখায়"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"যখন চার্জ করা হবে না তখন স্থিতি দন্ডের আইকনের ভিতরে ব্যাটারি স্তরের শতকার হার দেখায়"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"বড় করুন"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"বন্ধ করুন"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"খারিজ করতে নিচের দিকে টেনে আনুন"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"মেনু"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f09bb1f..fc246c4 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -153,9 +153,9 @@
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="8274017118472455155">"Nema SIM kartice."</string>
- <string name="accessibility_cell_data" msgid="5326139158682385073">"Mobilni podaci"</string>
- <string name="accessibility_cell_data_on" msgid="5927098403452994422">"Mobilni podaci su uključeni"</string>
- <string name="accessibility_cell_data_off" msgid="443267573897409704">"Mobilni podaci su isključeni"</string>
+ <string name="accessibility_cell_data" msgid="5326139158682385073">"Prijenos podataka na mobilnoj mreži"</string>
+ <string name="accessibility_cell_data_on" msgid="5927098403452994422">"Prijenos podataka na mobilnoj mreži je uključen"</string>
+ <string name="accessibility_cell_data_off" msgid="443267573897409704">"Prijenos podataka na mobilnoj mreži je isključen"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Dijeljenje Bluetooth veze."</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Način rada u avionu."</string>
<string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN uključen."</string>
@@ -240,9 +240,9 @@
<string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"Punjenje"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G prijenos podataka je pauzirano"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G prijenos podataka je pauzirano"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="6801382439018099779">"Mobilni podaci su pauzirani"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="6801382439018099779">"Prijenos podataka je pauziran"</string>
<string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Prijenos podataka je pauziran"</string>
- <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"Dostigli ste ograničenje za prijenos podataka koje ste postavili. Više ne koristite mobilne podatke.\n\nUkoliko nastavite koristiti mobilne podatke, mogući su troškovi za prijenos podataka."</string>
+ <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"Dostigli ste ograničenje za prijenos podataka koje ste postavili. Više ne koristite prijenos podataka na mobilnoj mreži.\n\nUkoliko nastavite koristiti prijenos podataka na mobilnoj mreži, mogući su troškovi za prijenos podataka."</string>
<string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS signala"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija utvrđena GPS signalom"</string>
@@ -315,7 +315,7 @@
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Pristupna tačka"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavještenja"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
- <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prijenos podataka na mobilnoj mreži"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Prijenos podataka"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podataka"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Prekoračeno"</string>
@@ -412,16 +412,16 @@
<string name="profile_owned_footer" msgid="8021888108553696069">"Profil može biti nadziran"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Mreža može biti nadzirana"</string>
<string name="branded_vpn_footer" msgid="2168111859226496230">"Mreža može biti nadzirana"</string>
- <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni promet."</string>
- <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može pratiti vaš mrežni promet"</string>
+ <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni saobraćaj."</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može pratiti vaš mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"Uređajem upravlja vaša organizacija i povezan je s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s aplikacijom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="3294967280853150271">"Uređajem upravlja vaša organizacija"</string>
<string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>."</string>
<string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"Uređajem upravlja vaša organizacija i povezan je s VPN-ovima"</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s VPN-ovima"</string>
- <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Vaša organizacija može pratiti mrežni promet na vašem profilu."</string>
- <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može pratiti mrežni promet na vašem radnom profilu"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Vaša organizacija može pratiti mrežni saobraćaj na vašem profilu."</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može pratiti mrežni saobraćaj na vašem radnom profilu"</string>
<string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"Mreža može biti nadzirana"</string>
<string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"Uređaj je povezan s VPN-ovima"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"Radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -438,10 +438,10 @@
<string name="monitoring_button_view_policies" msgid="100913612638514424">"Prikaži pravila"</string>
<string name="monitoring_description_named_management" msgid="5281789135578986303">"Vašim uređajem upravlja organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš administrator može nadgledati i upravljati vašim postavkama, korporativnom pristupu, aplikacijama, podacima koji su povezani s vašim uređajem i informacijama o lokaciji vašeg uređaja.\n\nZa više informacija, obratite se svom administratoru."</string>
<string name="monitoring_description_management" msgid="4573721970278370790">"Vašim uređajem upravlja vaša organizacija.\n\nVaš administrator može nadgledati i upravljati vašim postavkama, korporativnom pristupu, aplikacijama, podacima koji su povezani s vašim uređajem i informacijama o lokaciji vašeg uređaja.\n\nZa više informacija, obratite se svom administratoru."</string>
- <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"Vaša organizacija je instalirala CA certifikat na ovom uređaju. Vaš promet preko sigurne mreže može se pratiti."</string>
- <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"Vaša organizacija je instalirala CA certifikat na vašem radnom profilu. Vaš promet preko sigurne mreže može se pratiti."</string>
- <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"CA certifikat je instaliran na ovom uređaju. Vaš promet preko sigurne mreže može se pratiti."</string>
- <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"Vaš administrator je uključio zapisivanje na mreži, čime se prati promet na vašem uređaju."</string>
+ <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"Vaša organizacija je instalirala CA certifikat na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"Vaša organizacija je instalirala CA certifikat na vašem radnom profilu. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"CA certifikat je instaliran na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju."</string>
<string name="monitoring_description_named_vpn" msgid="7403457334088909254">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može pratiti vašu aktivnost na mreži, uključujući e-poštu i web lokacije."</string>
<string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"Povezani ste s aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g> koje mogu pratiti vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web lokacije."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"Vaš radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
@@ -462,7 +462,7 @@
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
<string name="monitoring_description_app" msgid="1828472472674709532">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web lokacije."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
- <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste na aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vaše privatne aktivnosti na mreži, uključujući e-poštu, aplikacije i web stranice."</string>
+ <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste na aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vaše privatne aktivnosti na mreži, uključujući e-poštu, aplikacije i web lokacije."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se svom administratoru."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži."</string>
<string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"Otključano za korisnika <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
@@ -494,6 +494,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dvostruka višemelodijska frekvencija"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Pristupačnost"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Pozivi"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Zvono"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibriranje"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Isključi zvuk"</string>
@@ -506,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dodirnite da isključite zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Prikazane kontrole jačine zvuka za: %s. Prevucite prema gore za odbacivanje."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrole jačine zvuka sakrivene"</string>
+ <string name="output_title" msgid="5355078100792942802">"Izlaz za medijske fajlove"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Izlaz za telefonske pozive"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nije pronađen nijedan uređaj"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nije pronađen nijedan uređaj. Pokušajte uključiti <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth i Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Podešavač za korisnički interfejs sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži ugrađeni postotak baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazuje postotak nivoa baterije unutar ikone na statusnoj traci kada se baterija ne puni"</string>
@@ -731,6 +739,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da odbacite"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string>
@@ -768,7 +778,7 @@
<string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
<string name="go_to_web" msgid="2650669128861626071">"Idi na preglednik"</string>
- <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
+ <string name="mobile_data" msgid="7094582042819250762">"Prijenos podataka na mobilnoj mreži"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi veza je isključena"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Opcija Ne ometaj je isključena"</string>
@@ -780,6 +790,6 @@
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
<string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije koje rade u pozadini"</string>
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
- <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite li isključiti prijenos mobilnih podataka?"</string>
+ <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite li isključiti prijenos podataka na mobilnoj mreži?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index dacf9d7..4ff8e2c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -35,8 +35,8 @@
<string name="battery_low_title" msgid="6456385927409742437">"Queda poca bateria"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>."</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>. La funció Estalvi de bateria està activada."</string>
- <string name="invalid_charger" msgid="4549105996740522523">"Càrrega d\'USB no admesa.\nUtilitza només el carregador proporcionat."</string>
- <string name="invalid_charger_title" msgid="3515740382572798460">"La càrrega per USB no és compatible."</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Pujada d\'USB no admesa.\nUtilitza només el carregador proporcionat."</string>
+ <string name="invalid_charger_title" msgid="3515740382572798460">"La pujada per USB no és compatible."</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"Fes servir només el carregador proporcionat amb el dispositiu."</string>
<string name="battery_low_why" msgid="4553600287639198111">"Configuració"</string>
<string name="battery_saver_confirmation_title" msgid="2052100465684817154">"Vols activar la funció Estalvi de bateria?"</string>
@@ -342,7 +342,7 @@
<string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Divideix la pantalla cap a la dreta"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
- <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la càrrega"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la pujada"</string>
<string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"No s\'està carregant"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string>
<string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
@@ -369,9 +369,9 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silenci\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Només\ninterr. prior."</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Només\nalarmes"</string>
- <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la càrrega)"</string>
- <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Càrrega ràpida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar-se)"</string>
- <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Càrrega lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar-se)"</string>
+ <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la pujada)"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Pujada ràpida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar-se)"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Pujada lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar-se)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Canvia d\'usuari"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Canvia d\'usuari. Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toca per silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Es mostren %s controls de volum. Llisca cap amunt per ignorar-ho."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Els controls de volum estan amagats"</string>
+ <string name="output_title" msgid="5355078100792942802">"Sortida de contingut multimèdia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Sortida de trucades"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No s\'ha trobat cap dispositiu"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No s\'ha trobat cap dispositiu. Prova d\'activar <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth i Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Personalitzador d\'interfície d\'usuari"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra el percentatge de la bateria inserit"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostra el percentatge del nivell de bateria dins de la icona de la barra d\'estat quan no s\'estigui carregant"</string>
@@ -584,7 +591,7 @@
<item quantity="one">%d minut</item>
</plurals>
<string name="battery_panel_title" msgid="7944156115535366613">"Consum de la bateria"</string>
- <string name="battery_detail_charging_summary" msgid="1279095653533044008">"La funció Estalvi de bateria no està disponible durant la càrrega"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"La funció Estalvi de bateria no està disponible durant la pujada"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Estalvi de bateria"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Redueix el rendiment i les dades en segon pla"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"Botó <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrossega cap avall per ignorar-ho"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4166697..9c7de6a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -509,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Klepnutím vypnete zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Ovládací prvky hlasitosti aplikace %s jsou zobrazeny. Zavřete je přejetím prstem."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ovládací prvky hlasitosti jsou skryty"</string>
+ <string name="output_title" msgid="5355078100792942802">"Výstup médií"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Výstup telefonního hovoru"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nebyla nalezena žádná zařízení"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nebyla nalezena žádná zařízení. Zkuste zapnout <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth a Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Nástroj na ladění uživatelského rozhraní systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobrazovat vložené procento nabití baterie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Když neprobíhá nabíjení, zobrazit v ikoně na stavovém řádku procento nabití baterie"</string>
@@ -738,6 +745,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozbalit"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zavřít"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nápovědu zavřete přetažením dolů"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Nabídka"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 52446f8..5438434 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tryk for at slå lyden fra."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Lydstyrkeknapperne for %s er synlige. Stryg op for at lukke."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Lydstyrkeknapperne er skjult"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medieafspilning"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Udgang til telefonopkald"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Der blev ikke fundet nogen enheder"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Der blev ikke fundet nogen enheder. Prøv at aktivere <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth og Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis procent for det indbyggede batteri"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis procenttallet for batteriniveauet i ikonet for statusbjælken, når der ikke oplades"</string>
@@ -724,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Udvid"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Luk"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Indstillinger"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Træk nedad for at afvise"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 83a8e33..a68ad2a 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -507,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Zum Stummschalten tippen."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Lautstärkeregler von %s werden angezeigt. Zum Schließen nach oben wischen."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Lautstärkeregler ausgeblendet"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medienausgabe"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefonanrufausgabe"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Keine Geräte gefunden"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Keine Geräte gefunden. Aktiviere <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"WLAN"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth und WLAN"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Eingebettete Akku-Prozentzahl anzeigen"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prozentzahl für Akkustand in Statusleistensymbol anzeigen, wenn das Gerät nicht geladen wird"</string>
@@ -728,6 +735,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Maximieren"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimieren"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Schließen"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zum Schließen nach unten ziehen"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 9a61828..7464d31 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Πατήστε για σίγαση."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Εμφανίζονται τα στοιχεία ελέγχου έντασης %s. Σύρετε για παράβλεψη."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Έγινε απόκρυψη των στοιχείων ελέγχου έντασης"</string>
+ <string name="output_title" msgid="5355078100792942802">"Έξοδος μέσων"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Έξοδος τηλεφωνικής κλήσης"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Δεν βρέθηκαν συσκευές"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Δεν βρέθηκαν συσκευές. Δοκιμάστε να ενεργοποιήσετε την υπηρεσία <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth και Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Εμφάνιση ποσοστού ενσωματωμένης μπαταρίας"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Εμφάνιση ποσοστού επιπέδου μπαταρίας μέσα στο εικονίδιο της γραμμής κατάστασης όταν δεν γίνεται φόρτιση"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Ανάπτυξη"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Ελαχιστοποίηση"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Κλείσιμο"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Σύρετε προς τα κάτω για παράβλεψη"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Μενού"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 87a0ee5..b1b1626 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -492,6 +492,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dual multi-tone frequency"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibility"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Calls"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
@@ -499,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volume controls shown. Swipe up to dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volume controls hidden"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media output"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No devices found. Try turning on <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth and Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -720,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
@@ -756,7 +769,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+ <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 6756f86..420dd9d 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -492,6 +492,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dual multi-tone frequency"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibility"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Calls"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
@@ -499,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volume controls shown. Swipe up to dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volume controls hidden"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media output"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No devices found. Try turning on <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth and Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -720,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
@@ -756,7 +769,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+ <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 87a0ee5..b1b1626 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -492,6 +492,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dual multi-tone frequency"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibility"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Calls"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
@@ -499,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volume controls shown. Swipe up to dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volume controls hidden"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media output"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No devices found. Try turning on <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth and Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -720,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
@@ -756,7 +769,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+ <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 87a0ee5..b1b1626 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -492,6 +492,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dual multi-tone frequency"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibility"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Calls"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
@@ -499,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volume controls shown. Swipe up to dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volume controls hidden"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media output"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No devices found. Try turning on <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth and Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -720,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
@@ -756,7 +769,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+ <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 1d70422..4cc96c1 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -492,6 +492,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Dual multi tone frequency"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibility"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Calls"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Ring"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrate"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Mute"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
@@ -499,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap to mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s volume controls shown. Swipe up to dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volume controls hidden"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media output"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Phone call output"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No devices found"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No devices found. Try turning on <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth and Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -720,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimize"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Settings"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
@@ -756,7 +768,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+ <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d808119..6901686 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Presiona para silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Se muestran los controles de volumen de %s. Desliza el dedo para descartar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Controles de volumen ocultos"</string>
+ <string name="output_title" msgid="5355078100792942802">"Salida multimedia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Salida de llamada telefónica"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No se encontraron dispositivos"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No se encontraron dispositivos. Activa <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth y Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de la batería integrada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentaje del nivel de batería en el ícono de la barra de estado cuando no se está cargando"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra hacia abajo para descartar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está en modo de imagen en imagen"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 14c2818..a5d5c44 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -494,6 +494,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de tono dual"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accesibilidad"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Llamadas"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hacer sonar"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string>
@@ -504,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toca para silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s controles de volumen mostrados. Desliza el dedo hacia arriba para rechazar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Controles de volumen ocultos"</string>
+ <string name="output_title" msgid="5355078100792942802">"Salida multimedia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Salida de llamadas"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"No se ha podido encontrar ningún dispositivo"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"No se ha podido encontrar ningún dispositivo. Prueba a activar <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi‑Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth y Wi‑Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de batería insertado"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar el porcentaje del nivel de batería en el icono de la barra de estado cuando no se esté cargando"</string>
@@ -725,6 +733,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Mostrar"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Ajustes"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra hacia abajo para ignorar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está en imagen en imagen"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 3a5af25..84cbc44 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Puudutage vaigistamiseks."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s helitugevuse juhtnuppu on kuvatud. Loobumiseks pühkige üles."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Helitugevuse juhtnupud on peidetud"</string>
+ <string name="output_title" msgid="5355078100792942802">"Meediaväljund"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefonikõne väljund"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Seadmeid ei leitud"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Seadmeid ei leitud. Lülitage sisse teenus <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"WiFi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth ja WiFi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Süsteemi kasutajaliidese tuuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Kuva lisatud akutaseme protsent"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Akutaseme protsendi kuvamine olekuriba ikoonil, kui akut ei laeta"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Sule"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Loobumiseks lohistage alla"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menüü"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 87348de..85d3c6e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -226,8 +226,8 @@
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flasha aktibatuta dago."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flasha desaktibatu egin da."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flasha aktibatu egin da."</string>
- <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Koloreak alderantzikatzeko aukera desaktibatu egin da."</string>
- <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Koloreak alderantzikatzeko aukera aktibatu egin da."</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Koloreen alderantzikatzea desaktibatu egin da."</string>
+ <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Koloreen alderantzikatzea aktibatu egin da."</string>
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Konexioa partekatzeko aukera desaktibatu egin da."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Konexioa partekatzeko aukera aktibatu egin da."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Pantaila igortzeari utzi zaio."</string>
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Sakatu hau audioa desaktibatzeko."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Bolumena kontrolatzeko %s aukera daude ikusgai. Pasatu hatza gora baztertzeko."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ezkutatuta daude bolumena kontrolatzeko aukerak"</string>
+ <string name="output_title" msgid="5355078100792942802">"Multimedia-irteera"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefono-deiaren irteera"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Ez da aurkitu gailurik"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Ez da aurkitu gailurik. Aktibatu <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth konexioa"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi konexioa"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth eta Wi-Fi konexioak"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemako erabiltzaile-interfazearen konfiguratzailea"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Erakutsi txertatutako bateriaren ehunekoa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Erakutsi bateria-mailaren ehunekoa egoera-barraren ikonoan, kargatzen ari ez denean"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Zabaldu"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Itxi"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Baztertzeko, arrastatu behera"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menua"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bb77daa..834397d 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. برای بیصدا کردن ضربه بزنید."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"کنترلهای میزان صدای %s نشان داده شدند. برای نپذیرفتن انگشتتان را تند بکشید."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"کنترلهای صدا پنهان هستند"</string>
+ <string name="output_title" msgid="5355078100792942802">"خروجی رسانه"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"خروجی تماس تلفنی"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"دستگاهی پیدا نشد"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"دستگاهی پیدا نشد. <xliff:g id="SERVICE">%1$s</xliff:g> را روشن کنید"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"بلوتوث"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"بلوتوث و Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"تنظیمکننده واسط کاربری سیستم"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"نمایش درصد شارژ باتری جاسازی شده"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"نمایش درصد سطح باتری در نماد نوار وضعیت، هنگامی که باتری شارژ نمیشود"</string>
@@ -724,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"بستن"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"تنظیمات"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"برای نپذیرفتن، به پایین بکشید"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"منو"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> درحالت تصویر در تصویر است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3bebe4b..51a71de 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Mykistä napauttamalla."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Äänenvoimakkuuden säätimiä on näkyvissä (%s). Hylkää pyyhkäisemällä ylös."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Äänenvoimakkuuden säätimet piilotettiin."</string>
+ <string name="output_title" msgid="5355078100792942802">"Median äänentoisto"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Puhelun äänentoisto"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Laitteita ei löytynyt"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Laitteita ei löytynyt. Kokeile ottaa käyttöön <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth ja Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Näytä akun varaus kuvakkeessa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Näyttää akun varausprosentin tilapalkin kuvakkeessa, kun laitetta ei ladata."</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Laajenna"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Pienennä"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Sulje"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Hylkää vetämällä alas."</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Valikko"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a2dde85..1ddc394 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Touchez pour couper le son."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Commandes de volume %s affichées. Faire glisser vers le haut pour ignorer."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Les commandes de volume sont masquées"</string>
+ <string name="output_title" msgid="5355078100792942802">"Sortie multimédia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Sortie d\'appel téléphonique"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Aucun appareil trouvé"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Aucun appareil n\'a été trouvé. Essayez d\'activer le <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth et le Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de charge"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Afficher le pourcentage correspondant au niveau de la pile dans l\'icône de la barre d\'état lorsque l\'appareil n\'est pas en charge."</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 21952ae..f6e98a3 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -494,6 +494,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"DTMF"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibilité"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Appels"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Sonnerie"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibreur"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silencieux"</string>
@@ -504,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Appuyez pour ignorer."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Commandes de volume %s affichées. Faire glisser vers le haut pour ignorer."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Commandes de volume masquées"</string>
+ <string name="output_title" msgid="5355078100792942802">"Sortie multimédia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Sortie de l\'appel téléphonique"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Aucun appareil détecté"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Aucun appareil détecté. Essayez d\'activer le <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth et Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de la batterie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Affichez le pourcentage correspondant au niveau de la batterie dans l\'icône de la barre d\'état lorsque l\'appareil n\'est pas en charge."</string>
@@ -725,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9fbcdec..987ea59 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toca para silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Estanse mostrando os controis de volume de %s. Pasa o dedo cara a arriba para ignoralos."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ocultáronse os controis de volume"</string>
+ <string name="output_title" msgid="5355078100792942802">"Saída multimedia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Saída de chamadas telefónicas"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Non se atopou ningún dispositivo"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Non se atopou ningún dispositivo. Proba a activar <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wifi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth e wifi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador da IU do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaxe de batería inserida"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentaxe do nivel de batería na icona da barra de estado cando non está en carga"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Pechar"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra cara abaixo para ignorar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 418f31e..c024531 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"બ્લૂટૂથ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"દ્વિ બહુ ટોન આવર્તન"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ઍક્સેસિબિલિટી"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"કૉલ"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"રિંગ કરો"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"વાઇબ્રેટ"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"મ્યૂટ કરો"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. મ્યૂટ કરવા માટે ટૅપ કરો."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s વૉલ્યૂમ નિયંત્રણ બતાવ્યાં. છોડી દેવા માટે સ્વાઇપ કરો."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"વૉલ્યૂમ નિયંત્રણ છુપાવ્યાં"</string>
+ <string name="output_title" msgid="5355078100792942802">"મીડિયાનું આઉટપુટ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ફોન કૉલનો આઉટપુટ"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"કોઈ ઉપકરણો મળ્યા નથી"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"કોઈ ઉપકરણો મળ્યા નથી. <xliff:g id="SERVICE">%1$s</xliff:g>ને ચાલુ કરવાનો પ્રયાસ કરો"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"બ્લૂટૂથ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"વાઇ-ફાઇ"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"બ્લૂટૂથ અને વાઇ-ફાઇ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"સિસ્ટમ UI ટ્યૂનર"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"એમ્બેડ કરેલ બૅટરી ટકા બતાવો"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"જ્યારે ચાર્જ ન થઈ રહ્યું હોય ત્યારે સ્ટેટસ બાર આયકનની અંદર બૅટરી સ્તર ટકા બતાવો"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"બંધ કરો"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"છોડી દેવા માટે નીચે ખેંચો"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"મેનૂ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1acd6e7..f5f8c7c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"दोहरी बहु टोन आवृत्ति"</string>
<string name="stream_accessibility" msgid="301136219144385106">"सुलभता"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"कॉल"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"आवाज़ चालू है"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कंपन (वाइब्रेशन)"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"आवाज़ बंद है"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. म्यूट करने के लिए टैप करें."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s वॉल्यूम नियंत्रण दिखाए गए हैं. खारिज करने के लिए स्वाइप करें."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"वॉल्यूम नियंत्रण छिपे हुए हैं"</string>
+ <string name="output_title" msgid="5355078100792942802">"मीडिया आउटपुट"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"फ़ोन कॉल का आउटपुट"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"कोई डिवाइस नहीं मिला"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"कोई डिवाइस नहीं मिला. <xliff:g id="SERVICE">%1$s</xliff:g> को चालू करें"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ब्लूटूथ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"वाई-फ़ाई"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ब्लूटूथ और वाई-फ़ाई"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेड किया गया बैटरी प्रतिशत दिखाएं"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"जब चार्ज नहीं किया जा रहा हो तब स्टेटस बार आइकॉन में बैटरी लेवल का प्रतिशत दिखाएं"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तार करें"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"छोटा करें"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"बंद करें"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारिज करने के लिए नीचे खींचें और छोड़ें"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"मेन्यू"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> पिक्चर में पिक्चर के अंदर है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 7ba9111..7395b66 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dodirnite da biste isključili zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s kontrole glasnoće prikazane. Kliznite prstom prema gore da biste ih odbacili."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrole glasnoće skrivene"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medijski izlaz"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Izlaz telefonskih poziva"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nije pronađen nijedan uređaj"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nije pronađen nijedan uređaj. Pokušajte uključiti uslugu <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth i Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Ugađanje korisničkog sučelja sustava"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži ugrađeni postotak baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazivanje postotka razine baterije na ikoni trake statusa kada se ne puni"</string>
@@ -730,6 +737,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširivanje"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiziraj"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da biste odbacili"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Izbornik"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8aa2c71..87ca49a 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Koppintson a némításhoz."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"A(z) %s hangvezérlői megjelenítve. Az elvetéshez húzza felfelé az ujját."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Hangvezérlők elrejtve"</string>
+ <string name="output_title" msgid="5355078100792942802">"Médiakimenet"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefonhívás-kimenet"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nem találhatók eszközök"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nem találhatók eszközök. Próbálja meg a(z) <xliff:g id="SERVICE">%1$s</xliff:g> bekapcsolásával"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth és Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kezelőfelület-hangoló"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"A beépített akkumulátor töltöttségi szintjének megjelenítése"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Az akkumulátor töltöttségi szintjének megjelenítése az állapotsori ikonban, amikor az eszköz nem töltődik"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Bezárás"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Elvetéshez húzza lefelé"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 2841074..b6172c8 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s։ Հպեք՝ ձայնը անջատելու համար։"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ձայնի ուժգնության կառավարները ցուցադրված են: Մատը սահեցրեք վերև՝ փակելու համար:"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ձայնի ուժգնության կառավարները թաքցված են"</string>
+ <string name="output_title" msgid="5355078100792942802">"Մեդիա արտածում"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Հեռախոսազանգի հնչեցում"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Սարքեր չեն գտնվել"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Սարքեր չեն գտնվել: Միացրեք <xliff:g id="SERVICE">%1$s</xliff:g>-ը"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth-ը և Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Համակարգի ՕՄ-ի կարգավորիչ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ցուցադրել ներկառուցված մարտկոցի տոկոսայնությունը"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Ցուցադրել մարտկոցի լիցքավորման տոկոսայնությունը կարգավիճակի գոտու պատկերակի վրա, երբ այն չի լիցքավորվում"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Ընդարձակել"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Ծալել"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Փակել"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Քաշեք վար՝ փակելու համար"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Ընտրացանկ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f8604e3..66ebb86 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Frekuensi multinada ganda"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Aksesibilitas"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Telepon"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Dering"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Getar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Nonaktifkan"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tap untuk menonaktifkan."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Kontrol volume %s ditampilkan. Geser ke atas untuk menutup."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrol volume disembunyikan"</string>
+ <string name="output_title" msgid="5355078100792942802">"Keluaran media"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Keluaran panggilan telepon"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Perangkat tidak ditemukan"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Tidak ditemukan perangkat. Coba aktifkan <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth dan Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Penyetel Antarmuka Pengguna Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tampilkan persentase baterai yang tersemat"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Tampilkan persentase tingkat baterai dalam ikon bilah status saat tidak mengisi daya"</string>
@@ -723,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Luaskan"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk menutup"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 66530bd..35bf451 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Ýttu til að þagga."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s stýringar fyrir hljóðstyrk sýnilegar. Strjúktu upp til að hunsa."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Stýringar fyrir hljóðstyrk faldar"</string>
+ <string name="output_title" msgid="5355078100792942802">"Margmiðlunarúttak"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Úttak símtals"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Engin tæki fundust"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Engin tæki fundust. Prófaðu að kveikja á <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth og Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Fínstillingar kerfisviðmóts"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Sýna innfellda rafhlöðustöðu"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Sýna rafhlöðustöðuna í stöðustikunni þegar tækið er ekki í hleðslu"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Stækka"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minnka"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Loka"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Draga niður til að hunsa"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Valmynd"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c15e4b6..fec534d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -494,9 +494,10 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Frequenza multipla dual tone"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accessibilità"</string>
- <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Suoneria"</string>
- <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrazione"</string>
- <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Disattiva audio"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Chiamate"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Attiva suoneria"</string>
+ <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Attiva vibrazione"</string>
+ <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Disattiva suoneria"</string>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tocca per riattivare l\'audio."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tocca per attivare la vibrazione. L\'audio dei servizi di accessibilità può essere disattivato."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tocca per disattivare l\'audio. L\'audio dei servizi di accessibilità può essere disattivato."</string>
@@ -504,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tocca per disattivare l\'audio."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s comandi del volume mostrati. Fai scorrere verso l\'alto per ignorare."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Comandi del volume nascosti"</string>
+ <string name="output_title" msgid="5355078100792942802">"Uscita contenuti multimediali"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Uscita telefonate"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nessun dispositivo trovato"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nessun dispositivo trovato. Prova ad attivare <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth e Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Ottimizzatore UI di sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra percentuale batteria incorporata"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostra la percentuale di carica della batteria nell\'icona della barra di stato quando non è in carica"</string>
@@ -725,6 +733,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Espandi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Riduci a icona"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Chiudi"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Impostazioni"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trascina verso il basso per ignorare"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index cbbffa9..276fa33 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -31,9 +31,9 @@
<item quantity="other">%d מסכים ב’סקירה‘</item>
<item quantity="one">מסך אחד ב’סקירה‘</item>
</plurals>
- <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"אין התראות"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"אין הודעות"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתמשך"</string>
- <string name="status_bar_latest_events_title" msgid="6594767438577593172">"התראות"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"הודעות"</string>
<string name="battery_low_title" msgid="6456385927409742437">"עוצמת הסוללה נמוכה"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. הופעלה תכונת החיסכון בסוללה."</string>
@@ -49,7 +49,7 @@
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"סיבוב אוטומטי של המסך"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"השתק"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"אוטומטי"</string>
- <string name="status_bar_settings_notifications" msgid="397146176280905137">"התראות"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"הודעות"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth קשור"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"הגדר שיטות קלט"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"מקלדת פיזית"</string>
@@ -166,7 +166,7 @@
<string name="accessibility_battery_level" msgid="7451474187113371965">"<xliff:g id="NUMBER">%d</xliff:g> אחוזים של סוללה."</string>
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"טעינת סוללה, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> אחוז."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"הגדרות מערכת"</string>
- <string name="accessibility_notifications_button" msgid="4498000369779421892">"התראות"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"הודעות"</string>
<string name="accessibility_overflow_action" msgid="5681882033274783311">"הצגת כל ההודעות"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"נקה התראה"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS מופעל."</string>
@@ -248,7 +248,7 @@
<string name="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
- <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההודעות."</string>
<string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
<item quantity="two">יש בפנים עוד <xliff:g id="NUMBER_1">%s</xliff:g> הודעות.</item>
@@ -371,7 +371,7 @@
<string name="interruption_level_priority" msgid="6426766465363855505">"עדיפות בלבד"</string>
<string name="interruption_level_alarms" msgid="5226306993448328896">"התראות בלבד"</string>
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"שקט\nמוחלט"</string>
- <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"התראות בעדיפות\nבלבד"</string>
+ <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"הודעות בעדיפות\nבלבד"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"התראות\nבלבד"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"טוען (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"בטעינה מהירה (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד למילוי)"</string>
@@ -470,7 +470,7 @@
<string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"הנעילה בוטלה על ידי <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> פועל"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"המכשיר יישאר נעול עד שתבטל את נעילתו באופן ידני"</string>
- <string name="hidden_notifications_title" msgid="7139628534207443290">"קבל התראות מהר יותר"</string>
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"קבל הודעות מהר יותר"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"צפה בהן לפני שתבטל נעילה"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"לא, תודה"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"הגדר"</string>
@@ -507,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. הקש כדי להשתיק."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s פקדי עוצמת הקול גלויים. החלק כלפי מעלה כדי לסגור."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"פקדי עוצמת הקול מוסתרים"</string>
+ <string name="output_title" msgid="5355078100792942802">"פלט מדיה"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"פלט שיחת טלפון"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"לא נמצאו מכשירים"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"לא נמצאו מכשירים. יש לנסות להפעיל <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth ו-Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"הצג בשורת הסטטוס את אחוז עוצמת הסוללה"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"הצג את אחוז עוצמת הסוללה בתוך הסמל שבשורת הסטטוס כשהמכשיר אינו בטעינה"</string>
@@ -555,9 +562,9 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"בעזרת פקדים של הודעות הפעלה, תוכל להגדיר רמת חשיבות מ-0 עד 5 להודעות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצג בראש רשימת ההודעות \n- אפשר הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מנע הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n- הסתר ממסך הנעילה ומשורת הסטטוס \n- הצג בתחתית רשימת ההודעות \n\n"<b>"רמה 0"</b>" \n- חסום את כל ההודעות מהאפליקציה"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"הודעות"</string>
<string name="notification_channel_disabled" msgid="2139193533791840539">"לא תקבל את ההודעות האלה יותר"</string>
- <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> קטגוריות של התראות"</string>
+ <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> קטגוריות של הודעות"</string>
<string name="notification_default_channel_desc" msgid="2506053815870808359">"האפליקציה הזו לא תומכת בקטגוריות של הודעות"</string>
- <string name="notification_unblockable_desc" msgid="3561016061737896906">"לא ניתן לכבות התראות של האפליקציה הזאת"</string>
+ <string name="notification_unblockable_desc" msgid="3561016061737896906">"לא ניתן לכבות הודעות של האפליקציה הזאת"</string>
<plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
<item quantity="two">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item>
<item quantity="many">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item>
@@ -736,6 +743,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"סגור"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"גרור למטה כדי לסגור"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"תפריט"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index f840225..1cff43b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s。タップしてミュートします。"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s の音量調節が表示されています。閉じるには、上にスワイプします。"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"音量調節を非表示にしました"</string>
+ <string name="output_title" msgid="5355078100792942802">"メディア出力"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"通話の出力"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"デバイスが見つかりません"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"デバイスが見つかりません。<xliff:g id="SERVICE">%1$s</xliff:g> をオンにしてみてください"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth と Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"システムUI調整ツール"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"内蔵電池の残量の割合を表示する"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"充電していないときには電池残量の割合をステータスバーアイコンに表示する"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"閉じる"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"下にドラッグして閉じる"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"メニュー"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 933a5e3..870c896 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ტონალური აკრეფა"</string>
<string name="stream_accessibility" msgid="301136219144385106">"მარტივი წვდომა"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"ზარები"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"დარეკვა"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ვიბრაცია"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"დადუმება"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. შეეხეთ დასადუმებლად."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s-ის ხმის მართვის საშუალებები დამალულია. დასახურად, გადაფურცლეთ ზემოთ."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ხმის მართვის საშუალებები დამალულია"</string>
+ <string name="output_title" msgid="5355078100792942802">"მედია გამომავალი"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"სატელეფონო ზარის გამომავალი სიგნალი"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"მოწყობილობები ვერ მოიძებნა"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"მოწყობილობები ვერ მოიძებნა. ცადეთ <xliff:g id="SERVICE">%1$s</xliff:g>-ის ჩართვა"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth და Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"სისტემის UI ტუნერი"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ჩამაგრებული ბატარეის პროცენტის ჩვენება"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ბატარეის დონის პროცენტის ჩვენება სტატუსის ზოლის ხატულას შიგნით, როდესაც არ იტენება"</string>
@@ -723,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"გაშლა"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ჩაკეცვა"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"დახურვა"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"დასახურად ჩავლებით ჩამოიტანეთ ქვემოთ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"მენიუ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index a9e6ffe..c4ae759 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Дыбысын өшіру үшін түртіңіз."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s дыбысты басқару элементтері көрсетулі. Сырғыту арқылы жабыңыз."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Дыбысты басқару элементтері жасырын"</string>
+ <string name="output_title" msgid="5355078100792942802">"Meдиа шығысы"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Телефон қоңырау шығысы"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Ешқандай құрылғы табылмады"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Ешқандай құрылғы табылмады. <xliff:g id="SERVICE">%1$s</xliff:g> қосып көріңіз"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth және Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Жүйелік пайдаланушылық интерфейс тюнері"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ендірілген батарея пайыздық шамасын көрсету"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Зарядталмай тұрғанда, күй жолағы белгішесінің ішінде батарея деңгейінің пайыздық шамасын көрсетеді"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Жаю"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Кішірейту"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Жабу"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Жабу үшін төмен қарай сүйреңіз"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Mәзір"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"сурет ішіндегі сурет\" режимінде"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 5819f2a..12733f1 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s ។ ចុចដើម្បីបិទសំឡេង។"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"អង្គគ្រប់គ្រងកម្រិតសំឡេង %s បានបង្ហាញ។ អូសឡើងលើដើម្បីបដិសេធ។"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"អង្គគ្រប់គ្រងកម្រិតសំឡេងបានលាក់"</string>
+ <string name="output_title" msgid="5355078100792942802">"លទ្ធផលមេឌៀ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"លទ្ធផលនៃការហៅទូរសព្ទ"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"រកមិនឃើញឧបករណ៍ទេ"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"រកមិនឃើញឧបករណ៍ទេ។ សាកល្បងបើក <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ប៊្លូធូស"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ប៊្លូធូស និង Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"កម្មវិធីសម្រួល UI ប្រព័ន្ធ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"បង្ហាញភាគរយថាមពលថ្មដែលបានបង្កប់"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"បង្ហាញភាគរយនៃកម្រិតថាមពលថ្មនៅក្នុងរូបតំណាងរបារស្ថានភាពនៅពេលមិនសាកថ្ម"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"បិទ"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"អូសចុះក្រោមដើម្បីបដិសេធ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"ម៉ឺនុយ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5e7e1e2..b492fd4 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ಬ್ಲೂಟೂತ್"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ಡ್ಯುಯಲ್ ಬಹು ಟೋನ್ ಆವರ್ತನೆ"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"ಕರೆಗಳು"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"ರಿಂಗ್"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ವೈಬ್ರೇಟ್"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"ಮ್ಯೂಟ್"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳನ್ನು ತೋರಿಸಲಾಗಿದೆ. ವಜಾಗೊಳಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
+ <string name="output_title" msgid="5355078100792942802">"ಮೀಡಿಯಾ ಔಟ್ಪುಟ್"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ಫೋನ್ ಕರೆ ಔಟ್ಪುಟ್"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ಯಾವ ಸಾಧನಗಳೂ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ಯಾವುದೇ ಸಾಧನಗಳು ಪತ್ತೆಯಾಗಿಲ್ಲ. <xliff:g id="SERVICE">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ಬ್ಲೂಟೂತ್"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"ವೈ-ಫೈ"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ಬ್ಲೂಟೂತ್ ಮತ್ತು ವೈ-ಫೈ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ಎಂಬೆಡ್ ಮಾಡಲಾದ ಬ್ಯಾಟರಿ ಶೇಕಡಾ ತೋರಿಸಿ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ಚಾರ್ಜ್ ಮಾಡದಿರುವಾಗ ಸ್ಥಿತಿ ಪಟ್ಟಿ ಐಕಾನ್ ಒಳಗೆ ಬ್ಯಾಟರಿ ಮಟ್ಟದ ಶೇಕಡಾವನ್ನು ತೋರಿಸಿ"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ಮುಚ್ಚಿ"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ವಜಾಗೊಳಿಸಲು ಕೆಳಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"ಮೆನು"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಲ್ಲಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d86c32f..7fa87ed 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. 탭하여 음소거로 설정하세요."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s 볼륨 컨트롤이 표시됩니다. 닫으려면 위로 스와이프합니다."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"볼륨 컨트롤 숨김"</string>
+ <string name="output_title" msgid="5355078100792942802">"미디어 출력"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"전화 통화 출력"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"기기를 찾을 수 없음"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"기기를 찾을 수 없습니다. <xliff:g id="SERVICE">%1$s</xliff:g>을(를) 사용 설정해 보세요"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"블루투스"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"블루투스 및 Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"시스템 UI 튜너"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"내장형 배터리 잔량 비율 표시"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"충전 중이 아닌 경우 상태 표시줄 아이콘 내에 배터리 잔량 비율 표시"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"닫기"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"아래로 드래그하여 닫기"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"메뉴"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index e10e2b0..e3f1fa3 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Үнүн өчүрүү үчүн басыңыз."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s үндү башкаруу элементтери көрсөтүлгөн. Этибарга албоо үчүн өйдө серпип коюңуз."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Үндү башкаруу элементтери жашырылган"</string>
+ <string name="output_title" msgid="5355078100792942802">"Медиа түзмөк"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Телефон чалуу"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Түзмөктөр табылган жок"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Түзмөктөр табылган жок. <xliff:g id="SERVICE">%1$s</xliff:g> кызматын күйгүзүп көрүңүз"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi‑Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth жана Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Батарянын кубатнын деңгээли пайыз менен көрсөтлсүн"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Түзмөк кубаттанбай турганда, батареянын деңгээли статус тилкесинде көрүнүп турат"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Жайып көрсөтүү"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Кичирейтүү"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Жабуу"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Четке кагуу үчүн төмөн сүйрөңүз"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 2587a20..fe262ee 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. ແຕະເພື່ອປິດສຽງ."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"ສະແດງສ່ວນຄວບຄຸມສຽງ %s ແລ້ວ. ປັດອອກຂ້າງເພື່ອປິດໄວ້."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ເຊື່ອງສ່ວນຄວບຄຸມສຽງແລ້ວ"</string>
+ <string name="output_title" msgid="5355078100792942802">"ມີເດຍເອົ້າພຸດ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ເອົ້າພຸດສາຍໂທອອກ"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ບໍ່ພົບອຸປະກອນ"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ບໍ່ພົບອຸປະກອນ. ກະລຸນາລອງເປີດ <xliff:g id="SERVICE">%1$s</xliff:g> ກ່ອນ"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth ແລະ Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ສະແດງເປີເຊັນແບັດເຕີຣີທີ່ຕິດມາ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ສະແດງເປີເຊັນລະດັບແບັດເຕີຣີຢູ່ດ້ານໃນໄອຄອນແຖບສະຖານະ ເມື່ອບໍ່ສາກຢູ່"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ຂະຫຍາຍ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ຫຍໍ້"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ປິດ"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ລາກລົງເພື່ອປິດໄວ້"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"ເມນູ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1c97452..5530fc9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -507,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Palieskite, kad nutildytumėte."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Rodomi „%s“ garsumo valdikliai. Perbraukite į viršų, kad atsisakytumėte."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Garsumo valdikliai paslėpti"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medijos išvestis"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefono skambučių išvestis"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Įrenginių nerasta"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Įrenginių nerasta. Bandykite įjungti „<xliff:g id="SERVICE">%1$s</xliff:g>“"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"„Bluetooth“ ir „Wi-Fi“"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemos naudotojo sąsajos derinimo priemonė"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rodyti įterptą akumuliat. įkrovos procentinę vertę"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Rodyti akumuliatoriaus įkrovos lygio procentinę vertę būsenos juostos piktogramoje, kai įrenginys nėra įkraunamas"</string>
@@ -736,6 +743,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Uždaryti"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nuvilkite žemyn, kad atsisakytumėte"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c14eb3f..574d898 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Pieskarieties, lai izslēgtu skaņu."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Tiek rādītas %s skaļuma vadīklas. Velciet augšup, lai nerādītu."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Skaļuma vadīklas paslēptas"</string>
+ <string name="output_title" msgid="5355078100792942802">"Multivides izvade"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Tālruņa zvana izvade"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nav atrasta neviena ierīce"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nav atrasta neviena ierīce. Ieslēdziet <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth un Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistēmas saskarnes regulators"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rādīt akumulatora uzlādes līmeni procentos"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Rādīt akumulatora uzlādes līmeni procentos statusa joslas ikonā, kad netiek veikta uzlāde"</string>
@@ -730,6 +737,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Aizvērt"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Velciet lejup, lai noraidītu"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Izvēlne"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index e30085c..b64217d 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Допрете за да се исклучи звукот."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Прикажани се контролите за јачина на звукот на %s. Повлечете нагоре за да отфрлите."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Скриени се контролите за јачина на звукот"</string>
+ <string name="output_title" msgid="5355078100792942802">"Излез за аудиовизуелни содржини"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Излез за телефонски повик"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Не се најдени уреди"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Не се најдени уреди. Обидете се да вклучите <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth и Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Адаптер на УИ на системот"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Прикажи вграден процент на батеријата"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Прикажи процент на ниво на батеријата во внатрешноста на иконата со статусна лента кога не се полни"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Проширете"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Минимизирај"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Повлечете надолу за да отфрлите"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 385331e..aba4260 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ബ്ലൂടൂത്ത്"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ഡ്യുവൽ മൾട്ടി റ്റോൺ ഫ്രീക്വൻസി"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ഉപയോഗസഹായി"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"കോളുകൾ"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"റിംഗ് ചെയ്യുക"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"വൈബ്രേറ്റ് ചെയ്യുക"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"മ്യൂട്ട് ചെയ്യുക"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s വോളിയം നിയന്ത്രണങ്ങൾ കാണിച്ചിരിക്കുന്നു. ഡിസ്മിസ് ചെയ്യുന്നതിന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്യുക."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"വോളിയം നിയന്ത്രണങ്ങൾ മറച്ചിരിക്കുന്നു"</string>
+ <string name="output_title" msgid="5355078100792942802">"മീഡിയ ഔട്ട്പുട്ട്"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ഫോൺ കോൾ ഔട്ട്പുട്ട്"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ഉപകരണങ്ങളൊന്നും കണ്ടെത്തിയില്ല"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ഉപകരണങ്ങളൊന്നും കണ്ടെത്തിയില്ല. <xliff:g id="SERVICE">%1$s</xliff:g> ഓണാക്കുന്നത് പരീക്ഷിക്കുക"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"വൈഫൈ"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth-ഉം വൈഫൈയും"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"സിസ്റ്റം UI ട്യൂണർ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"എംബഡ് ചെയ്ത ബാറ്ററി ശതമാനം കാണിക്കുക"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ചാർജ്ജുചെയ്യാതിരിക്കുമ്പോൾ സ്റ്റാറ്റസ് ബാർ ഐക്കണിൽ ബാറ്ററി ലെവൽ ശതമാനം കാണിക്കുക"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"അവസാനിപ്പിക്കുക"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"തള്ളിക്കളയാൻ താഴേക്ക് വലിച്ചിടുക"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"മെനു"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിലാണ്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 480956c..42bd38b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -503,6 +503,13 @@
<!-- no translation found for volume_dialog_accessibility_shown_message (1834631467074259998) -->
<skip />
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Түвшний удирдлагыг нуусан"</string>
+ <string name="output_title" msgid="5355078100792942802">"Медиа гаралт"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Утасны дуудлагын гаралт"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Төхөөрөмж олдсонгүй"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Төхөөрөмж олдсонгүй. <xliff:g id="SERVICE">%1$s</xliff:g>-г асааж үзнэ үү"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth болон Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Системийн UI Тохируулагч"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Залгаатай тэжээлийн хувийг харуулах"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Тэжээлийн хувийг цэнэглээгүй байх үед статусын хэсэгт харуулна уу"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Хаах"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Хаахын тулд доош чирэх"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Цэс"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 8a0d661..aaf907e 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"दुहेरी एकाधिक टोन वारंंवारता"</string>
<string name="stream_accessibility" msgid="301136219144385106">"प्रवेशयोग्यता"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"कॉल"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"रिंग करा"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कंपन"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"म्युट करा"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. नि:शब्द करण्यासाठी टॅप करा."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s आवाज नियंत्रणे दर्शविली. डिसमिस करण्यासाठी वर स्वाइप करा."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"आवाज नियंत्रणे लपविली"</string>
+ <string name="output_title" msgid="5355078100792942802">"मीडिया आउटपुट"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"फोन कॉल आउटपुट"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"कोणतीही डिव्हाइस सापडली नाहीत"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"कोणतीही डिव्हाइस सापडली नाहीत. <xliff:g id="SERVICE">%1$s</xliff:g> चालू करून पाहा"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ब्लुटूथ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"वाय-फाय"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ब्लुटूथ आणि वाय-फाय"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम UI ट्युनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेडेड बॅटरी टक्केवारी दर्शवा"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"चार्ज होत नसताना स्टेटस बार चिन्हामध्ये बॅटरी पातळी टक्केवारी दर्शवा"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"बंद करा"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"डिसमिस करण्यासाठी खाली ड्रॅग करा"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"मेनू"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index e074875..118d2c7 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Ketik untuk meredam."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s kawalan kelantangan ditunjukkan. Leret ke atas untuk mengetepikan."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kawalan kelantangan disembunyikan"</string>
+ <string name="output_title" msgid="5355078100792942802">"Output media"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Output panggilan telefon"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Tiada peranti ditemui"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Tiada peranti ditemui. Cuba hidupkan <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth dan Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Penala UI Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tunjukkan peratusan bateri terbenam"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Tunjukkan peratusan aras bateri dalam ikon bar status semasa tidak mengecas"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk mengetepikan"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 22375b4..faca352 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ဘလူးတုသ်"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"နှစ်လိုင်းပေါင်း အသံပေါင်းစုံ ကြိမ်နှုန်း"</string>
<string name="stream_accessibility" msgid="301136219144385106">"အများသုံးစွဲနိုင်မှု"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"ခေါ်ဆိုမှုများ"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"အသံမြည်သည်"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"တုန်ခါသည်"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"အသံတိတ်သည်"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s။ အသံတိတ်ရန် တို့ပါ။"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"အသံအတိုးအလျှော့ခလုတ် %s ပြသထားပါသည်။ ပယ်ရန် အပေါ်သို့ပွတ်ဆွဲပါ။"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"အသံအတိုးအလျှော့ခလုတ်များကို ဝှက်ထားပါသည်"</string>
+ <string name="output_title" msgid="5355078100792942802">"မီဒီယာ အထွက်"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ဖုန်းလိုင်း အထွက်"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"မည်သည့် စက်ပစ္စည်းမျှ မတွေ့ပါ"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"မည်သည့် စက်ပစ္စည်းမျှ မတွေ့ပါ။ <xliff:g id="SERVICE">%1$s</xliff:g> ကို ဖွင့်ကြည့်ပါ"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ဘလူးတုသ်"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi−Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ဘလူးတုသ်နှင့် Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"စနစ် UI ဖမ်းစက်"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"မြုတ်ထားသည့် ဘက်ထရီ ရာခိုင်နှုန်းကို ပြပါ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"အားမသွင်းနေစဉ်တွင် ဘတ်ထရီအဆင့် ရာခိုင်နှုန်းကို အခြေနေပြဘား အိုင်ကွန်တွင် ပြပါ"</string>
@@ -723,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ချဲ့ရန်"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ချုံ့ရန်"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ပိတ်ရန်"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"ဆက်တင်များ"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ပယ်ရန်အတွက် အောက်သို့ ပွတ်ဆွဲပါ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"မီနူး"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> သည် တစ်ခုပေါ် တစ်ခုထပ်၍ ဖွင့်ထားသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 661df03..fbcd197 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Trykk for å slå av lyden."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Volumkontrollene for %s vises. Sveip opp for å avvise dem."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volumkontrollene er skjult"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medieutdata"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Utgang for telefonsamtaler"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Fant ingen enheter"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Fant ingen enheter. Prøv å slå på <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth og Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis prosent for det innebygde batteriet"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis batterinivåprosenten inni statusfeltikonet når du ikke lader"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Lukk"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Dra ned for å avvise"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index dce9cc4..ceda3c5 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लुटुथ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"दोहोरो बहु टोनको फ्रिक्वेन्सी"</string>
<string name="stream_accessibility" msgid="301136219144385106">"पहुँच"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"कलहरू"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"घन्टी"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"कम्पन"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"म्युट गर्नुहोस्"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। म्यूट गर्न ट्याप गर्नुहोस्।"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s का भोल्युम सम्बन्धी नियन्त्रणहरूलाई देखाइएको छ। खारेज गर्नका लागि स्वाइप गर्नुहोस्।"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"भोल्युम सम्बन्धी नियन्त्रणहरूलाई लुकाइयो"</string>
+ <string name="output_title" msgid="5355078100792942802">"मिडियाको आउटपुट"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"फोन कलको आउटपुट"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"कुनै पनि यन्त्र भेटिएन"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"कुनै पनि यन्त्र भेटिएन। <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गरी हेर्नुहोस्"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ब्लुटुथ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ब्लुटुथ र Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"प्रणाली UI ट्युनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"इम्बेड गरिएको ब्याट्री प्रतिशत देखाउनुहोस्"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"चार्ज नगरेको बेला वस्तुस्थिति पट्टी आइकन भित्र ब्याट्री प्रतिशत स्तर देखाउनुहोस्"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"बन्द गर्नुहोस्"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारेज गर्न तल तान्नुहोस्"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"मेनु"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index ca0fa07..7139a63 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -199,7 +199,7 @@
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Vliegtuigmodus ingeschakeld."</string>
<string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Niet storen aan, alleen prioriteit."</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Niet storen aan, totale stilte."</string>
- <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Niet storen aan, alleen alarmen."</string>
+ <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Niet storen aan, alleen wekkers."</string>
<string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Niet storen."</string>
<string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Niet storen uit."</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Niet storen uitgeschakeld."</string>
@@ -215,7 +215,7 @@
<string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Locatiemelding aan."</string>
<string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"Locatiemelding uitgeschakeld."</string>
<string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"Locatiemelding ingeschakeld."</string>
- <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm is ingesteld op <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Wekker is ingesteld op <xliff:g id="TIME">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Paneel sluiten."</string>
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tijd."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tijd."</string>
@@ -265,7 +265,7 @@
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="8735855737575028208">"Niet storen"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Alleen prioriteit"</string>
- <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alleen alarmen"</string>
+ <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alleen wekkers"</string>
<string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Totale stilte"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
@@ -348,11 +348,11 @@
<string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_priority_introduction" msgid="1149025108714420281">"Je wordt niet gestoord door geluiden en trillingen, behalve bij alarmen, herinneringen, afspraken en specifieke bellers die je selecteert. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
- <string name="zen_alarms_introduction" msgid="4934328096749380201">"Je wordt niet gestoord door geluiden en trillingen, behalve bij alarmen. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
+ <string name="zen_priority_introduction" msgid="1149025108714420281">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers, herinneringen, afspraken en specifieke bellers die je selecteert. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
+ <string name="zen_alarms_introduction" msgid="4934328096749380201">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"Aanpassen"</string>
- <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"Hiermee worden ALLE geluiden en trillingen geblokkeerd, waaronder die voor alarmen, muziek, video\'s en games. Je kunt wel nog steeds bellen."</string>
- <string name="zen_silence_introduction" msgid="3137882381093271568">"Hiermee worden ALLE geluiden en trillingen geblokkeerd, waaronder die voor alarmen, muziek, video\'s en games."</string>
+ <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"Hiermee worden ALLE geluiden en trillingen geblokkeerd, waaronder die voor wekkers, muziek, video\'s en games. Je kunt wel nog steeds bellen."</string>
+ <string name="zen_silence_introduction" msgid="3137882381093271568">"Hiermee worden ALLE geluiden en trillingen geblokkeerd, waaronder die voor wekkers, muziek, video\'s en games."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder urgente meldingen onderaan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik nog eens om te openen"</string>
@@ -365,7 +365,7 @@
<string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Totale stilte. Hiermee worden schermlezers ook op stil gezet."</string>
<string name="interruption_level_none" msgid="6000083681244492992">"Totale stilte"</string>
<string name="interruption_level_priority" msgid="6426766465363855505">"Alleen prioriteit"</string>
- <string name="interruption_level_alarms" msgid="5226306993448328896">"Alleen alarmen"</string>
+ <string name="interruption_level_alarms" msgid="5226306993448328896">"Alleen wekkers"</string>
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Totale\nstilte"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Alleen\nprioriteit"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alleen\nalarmen"</string>
@@ -487,11 +487,12 @@
<string name="stream_system" msgid="7493299064422163147">"Systeem"</string>
<string name="stream_ring" msgid="8213049469184048338">"Bellen"</string>
<string name="stream_music" msgid="9086982948697544342">"Media"</string>
- <string name="stream_alarm" msgid="5209444229227197703">"Alarm"</string>
+ <string name="stream_alarm" msgid="5209444229227197703">"Wekker"</string>
<string name="stream_notification" msgid="2563720670905665031">"Melding"</string>
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Frequentie voor tweevoudige multitoon"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Toegankelijkheid"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Oproepen"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Bellen"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Trillen"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Dempen"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tik om te dempen."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Volumeknoppen van %s worden weergegeven. Veeg omhoog om te sluiten."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volumeknoppen verborgen"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media-uitvoer"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Uitvoer van telefoongesprek"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Geen apparaten gevonden"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Geen apparaten gevonden. Probeer <xliff:g id="SERVICE">%1$s</xliff:g> in te schakelen."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wifi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth en wifi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Systeem-UI-tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Percentage ingebouwde batterij weergeven"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Accupercentage weergeven in het pictogram op de statusbalk wanneer er niet wordt opgeladen"</string>
@@ -512,13 +520,13 @@
<string name="enable_demo_mode" msgid="4844205668718636518">"Demomodus inschakelen"</string>
<string name="show_demo_mode" msgid="2018336697782464029">"Demomodus weergeven"</string>
<string name="status_bar_ethernet" msgid="5044290963549500128">"Ethernet"</string>
- <string name="status_bar_alarm" msgid="8536256753575881818">"Alarm"</string>
+ <string name="status_bar_alarm" msgid="8536256753575881818">"Wekker"</string>
<string name="status_bar_work" msgid="6022553324802866373">"Werkprofiel"</string>
<string name="status_bar_airplane" msgid="7057575501472249002">"Vliegtuigmodus"</string>
<string name="add_tile" msgid="2995389510240786221">"Tegel toevoegen"</string>
<string name="broadcast_tile" msgid="3894036511763289383">"Tegel \'Uitzenden\'"</string>
- <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"U hoort je volgende alarm niet <xliff:g id="WHEN">%1$s</xliff:g> tenzij u dit voor die tijd uitschakelt"</string>
- <string name="zen_alarm_warning" msgid="444533119582244293">"U hoort je volgende alarm niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
+ <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g> tenzij je dit voor die tijd uitschakelt"</string>
+ <string name="zen_alarm_warning" msgid="444533119582244293">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="3980063409350522735">"om <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="4242179982586714810">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Snelle instellingen, <xliff:g id="TITLE">%s</xliff:g>."</string>
@@ -712,7 +720,7 @@
<string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Instellingen openen."</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Snelle instellingen openen."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Snelle instellingen sluiten."</string>
- <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Alarm is ingesteld."</string>
+ <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Wekker is ingesteld."</string>
<string name="accessibility_quick_settings_user" msgid="1567445362870421770">"Ingelogd als <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_no_internet" msgid="31890692343084075">"Geen internet."</string>
<string name="accessibility_quick_settings_open_details" msgid="4230931801728005194">"Details openen."</string>
@@ -723,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Sluiten"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep omlaag om te sluiten"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 43503d6..b141801 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"ਬਲੂਟੁੱਥ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ਦੂਹਰੀ ਮਲਟੀ ਟੋਨ ਆਵਰਤੀ"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ਪਹੁੰਚਯੋਗਤਾ"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"ਕਾਲਾਂ"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"ਘੰਟੀ"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"ਥਰਥਰਾਹਟ"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"ਮਿਊਟ"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ਅਵਾਜ਼ ਕੰਟਰੋਲ ਦਿਖਾਏ ਗਏ ਹਨ। ਖਾਰਜ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਲੁਕਾਏ ਗਏ ਹਨ"</string>
+ <string name="output_title" msgid="5355078100792942802">"ਮੀਡੀਆ ਆਊਟਪੁੱਟ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ਫ਼ੋਨ ਕਾਲ ਆਊਟਪੁੱਟ"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ਕੋਈ ਡੀਵਾਈਸ ਨਹੀਂ ਮਿਲੇ"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ਕੋਈ ਡੀਵਾਈਸ ਨਹੀਂ ਮਿਲੇ। <xliff:g id="SERVICE">%1$s</xliff:g> ਚਾਲੂ ਕਰਨ ਨੂੰ ਅਜ਼ਮਾਓ"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"ਬਲੂਟੁੱਥ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"ਵਾਈ-ਫਾਈ"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"ਬਲੂਟੁੱਥ ਅਤੇ ਵਾਈ-ਫਾਈ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI ਟਿਊਨਰ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ਜੋਡ਼ੀ ਗਈ ਬੈਟਰੀ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ਜਦੋਂ ਚਾਰਜ ਨਾ ਹੋ ਰਹੀ ਹੋਵੇ ਤਾਂ ਸਥਿਤੀ ਪੱਟੀ ਪ੍ਰਤੀਕ ਦੇ ਅੰਦਰ ਬੈਟਰੀ ਪੱਧਰ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ਖਾਰਜ ਕਰਨ ਲਈ ਹੇਠਾਂ ਘਸੀਟੋ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"ਮੀਨੂ"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ \'ਚ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e567e6ba..4c385b7 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -507,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Kliknij, by wyciszyć."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Wyświetlane są elementy sterowania głośnością aplikacji %s. Przesuń palcem, by odrzucić."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Elementy sterowania głośnością ukryte"</string>
+ <string name="output_title" msgid="5355078100792942802">"Wyjście multimediów"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Wyjście dla połączeń telefonicznych"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nie znaleziono urządzeń"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nie znaleziono urządzeń. Spróbuj włączyć <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth i Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kalibrator System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Pokaż procent naładowania baterii"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Pokaż procent naładowania baterii w ikonie na pasku stanu, gdy telefon się nie ładuje"</string>
@@ -736,10 +743,12 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozwiń"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizuj"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zamknij"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Przeciągnij w dół, by zamknąć"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string>
- <string name="pip_notification_message" msgid="5619512781514343311">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i ją wyłącz."</string>
+ <string name="pip_notification_message" msgid="5619512781514343311">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i wyłącz ją."</string>
<string name="pip_play" msgid="1417176722760265888">"Odtwórz"</string>
<string name="pip_pause" msgid="8881063404466476571">"Wstrzymaj"</string>
<string name="pip_skip_to_next" msgid="1948440006726306284">"Dalej"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 61aa901..8265895 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -387,7 +387,7 @@
<string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Remover"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Bem-vindo, convidado."</string>
- <string name="guest_wipe_session_message" msgid="8476238178270112811">"Deseja continuar a sessão?"</string>
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Recomeçar"</string>
<string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Sim, continuar"</string>
<string name="guest_notification_title" msgid="1585278533840603063">"Usuário convidado"</string>
@@ -494,6 +494,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Multifrequência de dois tons"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Acessibilidade"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Chamadas"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Tocar"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ignorar"</string>
@@ -504,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toque para silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s controles de volume exibidos. Deslize para cima para dispensar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Controles de volume ocultos"</string>
+ <string name="output_title" msgid="5355078100792942802">"Saída de mídia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Saída de chamada telefônica"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nenhum dispositivo foi encontrado"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nenhum dispositivo encontrado. Tente ativar o <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth e Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentagem de nível de bateria dentro do ícone da barra de status quando não estiver carregando"</string>
@@ -725,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 681d3e4..b676a24 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toque para desativar o som."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Controlos de volume %s apresentados. Deslize rapidamente para cima para ignorar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Controles de volume ocultados"</string>
+ <string name="output_title" msgid="5355078100792942802">"Saída de som multimédia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Saída de som de chamada telefónica"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nenhum dispositivo encontrado."</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nenhum dispositivo encontrado. Experimente ativar o <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth e Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador da interface do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar percentagem da bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar a percentagem do nível da bateria no ícone da barra de estado quando não estiver a carregar"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastar para baixo para ignorar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"A aplicação <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 61aa901..8265895 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -387,7 +387,7 @@
<string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Remover"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Bem-vindo, convidado."</string>
- <string name="guest_wipe_session_message" msgid="8476238178270112811">"Deseja continuar a sessão?"</string>
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Recomeçar"</string>
<string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Sim, continuar"</string>
<string name="guest_notification_title" msgid="1585278533840603063">"Usuário convidado"</string>
@@ -494,6 +494,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Multifrequência de dois tons"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Acessibilidade"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Chamadas"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Tocar"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Ignorar"</string>
@@ -504,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Toque para silenciar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s controles de volume exibidos. Deslize para cima para dispensar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Controles de volume ocultos"</string>
+ <string name="output_title" msgid="5355078100792942802">"Saída de mídia"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Saída de chamada telefônica"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nenhum dispositivo foi encontrado"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nenhum dispositivo encontrado. Tente ativar o <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth e Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentagem de nível de bateria dentro do ícone da barra de status quando não estiver carregando"</string>
@@ -725,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2a0744e..8168dfa 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -507,6 +507,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Atingeți pentru a dezactiva sunetul."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Comenzile de volum pentru %s sunt afișate. Glisați pentru a închide."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Comenzile de volum sunt ascunse"</string>
+ <string name="output_title" msgid="5355078100792942802">"Ieșire media"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Ieșire apel telefonic"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nu s-a găsit niciun dispozitiv"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nu s-au găsit dispozitive. Încercați să activați <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth și Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afișați procentajul bateriei încorporat"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Afișați procentajul cu nivelul bateriei în interiorul pictogramei din bara de stare, atunci când nu se încarcă"</string>
@@ -732,6 +739,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Extindeți"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Închideți"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trageți în jos pentru a închide"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ac4f5fe..9456615 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -498,6 +498,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Тональный набор"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Специальные возможности"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Вызовы"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Со звуком"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вибрация"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Без звука"</string>
@@ -508,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Нажмите, чтобы выключить звук."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Показаны регуляторы громкости: %s. Проведите вверх, чтобы скрыть."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Регуляторы громкости скрыты"</string>
+ <string name="output_title" msgid="5355078100792942802">"Выход мультимедиа"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Выход телефонных вызовов"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Устройств не найдено"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Устройств не найдено. Включите <xliff:g id="SERVICE">%1$s</xliff:g>."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth и Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показывать уровень заряда батареи в процентах"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Когда устройство работает в автономном режиме, процент заряда батареи показан в строке состояния"</string>
@@ -737,6 +745,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Закрыть"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Чтобы закрыть, потяните вниз"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 12f4838..338b522 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"බ්ලූටූත්"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"ද්විත්ව බහු ස්වර සංඛ්යාතය"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ප්රවේශ්යතාව"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"ඇමතුම්"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"නාද කරන්න"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"කම්පනය කරන්න"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"නිහඬ කරන්න"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s හඬ පරිමා පාලන පෙන්වයි. ඉවත දැමීමට ස්වයිප් කරන්න."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"හඩ පරිමා පාලන සඟවා ඇත"</string>
+ <string name="output_title" msgid="5355078100792942802">"මාධ්ය ප්රතිදානය"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"දුරකථන ඇමතුම් ප්රතිදානය"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"උපාංග හමු නොවිණි"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"උපාංග හමු නොවිණි. <xliff:g id="SERVICE">%1$s</xliff:g> ක්රියාත්මක කිරීම උත්සාහ කරන්න"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"බ්ලූටූත්"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"බ්ලූටූත් සහ Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"පද්ධති UI සුසරකය"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"කාවද්දන ලද බැටරි ප්රතිශතය පෙන්වන්න"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ආරෝපණය නොවන විට තත්ත්ව තීරු නිරූපකය ඇතුළත බැටරි මට්ටම් ප්රතිශතය පෙන්වන්න"</string>
@@ -723,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"දිග හරින්න"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"කුඩා කරන්න"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"වසන්න"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"සැකසීම්"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ඉවත ලෑමට පහළට ඇදගෙන යන්න"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"මෙනුව"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> පින්තූරය-තුළ-පින්තූරය තුළ වේ"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 694695c..49415a5 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -509,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Klepnutím vypnete zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Zobrazujú sa ovládacie prvky hlasitosti zariadenia %s. Prejdením prstom nahor to odmietnete."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ovládacie prvky hlasitosti sú skryté"</string>
+ <string name="output_title" msgid="5355078100792942802">"Výstup médií"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Výstup telefonického hovoru"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nenašli sa žiadne zariadenia"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nenašli sa žiadne zariadenia. Skúste zapnúť službu <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth a Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner používateľského rozhrania systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobraziť percentá vloženej batérie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Percentuálne zobrazenie nabitia batérie vnútri ikony v stavovom riadku, keď neprebieha nabíjanie"</string>
@@ -738,6 +745,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zavrieť"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zrušíte presunutím nadol"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Ponuka"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 10d0104..5ba1bb5 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -509,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dotaknite se, če želite izklopiti zvok."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Prikazani so ti kontrolniki za glasnost: %s. Povlecite navzgor za opustitev."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrolniki za glasnost so skriti."</string>
+ <string name="output_title" msgid="5355078100792942802">"Izhod predstavnosti"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Izhod telefonskih klicev"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Ni naprav"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Ni naprav. Poskusite vklopiti <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth in Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Uglaševalnik uporabniškega vmesnika sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži odstotek napolnjenosti vgraj. akumulatorja"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikaz odstotka napolnjenosti akumulatorja znotraj ikone v vrstici stanja, ko se ne polni"</string>
@@ -738,6 +745,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Razširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiraj"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zapri"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Nastavitve"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povlecite navzdol, da opustite"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v načinu slika v sliki"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 665177f..2d1591f 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Trokit për ta çaktivizuar."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Tregohen %s kontrolle volumi. Rrëshqit lart për ta larguar."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrollet e volumit janë fshehur"</string>
+ <string name="output_title" msgid="5355078100792942802">"Dalja e pajisjes"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Dalja e telefonatës"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Nuk u gjet asnjë pajisje"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Nuk u gjet asnjë pajisje. Provo të aktivizosh <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth dhe Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Shfaq përqindjen e baterisë së integruar"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Shfaq përqindjen e nivelit të baterisë brenda ikonës së shiritit të statusit kur nuk është duke u ngarkuar."</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Zgjero"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizo"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Mbyll"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zvarrit poshtë për të larguar"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menyja"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index cef0f69..99d8008 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Додирните да бисте искључили звук."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Контроле за јачину звука (%s) су приказане. Превуците нагоре да бисте их одбацили."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Контроле за јачину звука су сакривене"</string>
+ <string name="output_title" msgid="5355078100792942802">"Излаз медија"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Излаз за телефонски позив"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Није пронађен ниједан уређај"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Није пронађен ниједан уређај. Пробајте да укључите услугу <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth и Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Тјунер за кориснички интерфејс система"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Приказуј уграђени проценат батерије"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Приказивање нивоа напуњености батерије у процентима унутар иконе на статусној траци када се батерија не пуни"</string>
@@ -730,6 +737,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Превуците надоле да бисте одбили"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c8f8db4..2d267df 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Tryck här om du vill stänga av ljudet."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Volymkontrollerna för %s visas. Svep uppåt för att ignorera."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Volymkontrollerna är dolda"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medieuppspelning"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Utdata för samtal"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Inga enheter hittades"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Inga enheter hittades. Testa att aktivera <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth och Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Inställningar för systemgränssnitt"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Visa inbäddad batteriprocent"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Visa batterinivå i procent i statusfältsikonen när enheten inte laddas"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimera"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Stäng"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tryck och dra nedåt för att avvisa"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8fa370d..71285ad 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -79,7 +79,7 @@
<string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Angika kama kichezaji cha maudhui (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Angika kama kamera (PTP)"</string>
- <string name="installer_cd_button_title" msgid="2312667578562201583">"Sakinisha programu ya Kuhamisha Faili ya Android ya Mac"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Weka programu ya Kuhamisha Faili inayotumika kwenye Mac"</string>
<string name="accessibility_back" msgid="567011538994429120">"Nyuma"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Nyumbani"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menyu"</string>
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Gusa ili usitishe."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Inaonyesha %s ya vidhibiti vya sauti. Telezesha kidole juu ili uondoe."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Imeficha vidhibiti vya sauti"</string>
+ <string name="output_title" msgid="5355078100792942802">"Vifaa vya kutoa maudhui"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Vifaa vya kutoa sauti ya simu"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Hakuna vifaa vilivyopatikana"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Hakuna vifaa vilivyopatikana. Jaribu kuwasha <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth na Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kirekebishi cha kiolesura cha mfumo"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Onyesha asilimia ya betri iliyopachikwa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Onyesha asilimia ya kiwango cha betri ndani ya aikoni ya sehemu ya arifa inapokuwa haichaji"</string>
@@ -724,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Panua"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Punguza"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Funga"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Mipangilio"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Buruta ili uondoe"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 6568381..544cd79 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"புளூடூத்"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"டூயல் டோன் மல்டி ஃப்ரீக்வென்சி"</string>
<string name="stream_accessibility" msgid="301136219144385106">"அணுகல்தன்மை"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"அழைப்புகள்"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"ஒலி"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"அதிர்வு"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"அமைதி"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. ஒலியடக்க, தட்டவும்."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ஒலிக் கட்டுப்பாடுகள் காட்டப்பட்டன. நிராகரிக்க, மேலே ஸ்வைப் செய்யவும்."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ஒலிக் கட்டுப்பாடுகள் மறைக்கப்பட்டன"</string>
+ <string name="output_title" msgid="5355078100792942802">"மீடியா வெளியீடு"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ஃபோன் அழைப்பு வெளியீடு"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"சாதனங்கள் எதுவும் இல்லை"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"சாதனங்கள் எதுவும் இல்லை. <xliff:g id="SERVICE">%1$s</xliff:g>ஐ ஆன் செய்யவும்"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"புளூடூத்"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"வைஃபை"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"புளூடூத் மற்றும் வைஃபை"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"உள்ளிணைந்த பேட்டரி சதவீதத்தைக் காட்டு"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"சார்ஜ் செய்யாத போது, நிலைப் பட்டி ஐகானின் உள்ளே பேட்டரி அளவு சதவீதத்தைக் காட்டும்"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"விரி"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"மூடு"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"நிராகரிக்க, கீழே இழுக்கவும்"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"மெனு"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index fa7cb09..c2e0dce 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"బ్లూటూత్"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"డ్యూయల్ మల్టీ టోన్ ఫ్రీక్వెన్సీ"</string>
<string name="stream_accessibility" msgid="301136219144385106">"యాక్సెస్ సామర్థ్యం"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"కాల్లు"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"రింగ్"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"వైబ్రేట్"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"మ్యూట్"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. మ్యూట్ చేయడానికి నొక్కండి."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s వాల్యూమ్ నియంత్రణలు చూపబడ్డాయి. తీసివేయడానికి పైకి స్వైప్ చేయండి."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"వాల్యూమ్ నియంత్రణలు దాచబడ్డాయి"</string>
+ <string name="output_title" msgid="5355078100792942802">"మీడియా అవుట్పుట్"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"ఫోన్ కాల్ అవుట్పుట్"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"పరికరాలు ఏవీ కనుగొనబడలేదు"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"పరికరాలు ఏవీ కనుగొనబడలేదు. <xliff:g id="SERVICE">%1$s</xliff:g>ని ఆన్ చేసి ప్రయత్నించండి"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"బ్లూటూత్"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"బ్లూటూత్ మరియు Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"సిస్టమ్ UI ట్యూనర్"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"పొందుపరిచిన బ్యాటరీ శాతం చూపు"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ఛార్జింగ్లో లేనప్పుడు స్థితి పట్టీ చిహ్నం లోపల బ్యాటరీ స్థాయి శాతం చూపుతుంది"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"మూసివేయి"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"తీసివేయడానికి కిందికి లాగండి"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"మెను"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index d43efdd..5b31061 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s แตะเพื่อปิดเสียง"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ตัวควบคุมระดับเสียงแสดงอยู่ เลื่อนขึ้นเพื่อปิด"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ตัวควบคุมระดับเสียงซ่อนอยู่"</string>
+ <string name="output_title" msgid="5355078100792942802">"เอาต์พุตสื่อ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"เอาต์พุตการโทรออก"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"ไม่พบอุปกรณ์"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"ไม่พบอุปกรณ์ ลองเปิด <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"บลูทูธ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"บลูทูธและ Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"ตัวรับสัญญาณ UI ระบบ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"แสดงเปอร์เซ็นต์ของแบตเตอรี่ในตัว"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"แสดงเปอร์เซ็นต์ของระดับแบตเตอรี่ภายในไอคอนแถบสถานะเมื่อไม่มีการชาร์จ"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"ปิด"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ลากลงเพื่อปิด"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"เมนู"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 4aa9ca4..dadd57e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. I-tap upang i-mute."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Ipinapakita ang mga kontrol ng volume ng %s. Mag-swipe pataas upang i-dismiss."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Nakatago ang mga kontrol ng volume"</string>
+ <string name="output_title" msgid="5355078100792942802">"Output ng media"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Output ng tawag sa telepono"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Walang nakitang device"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Walang nakitang device. Subukang i-on ang <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth at Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner ng System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ipakita ang naka-embed na porsyento ng baterya"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Ipakita ang porsyento ng antas ng baterya na nasa icon ng status bar kapag nagcha-charge"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Isara"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"I-drag pababa upang i-dismiss"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d028fdd..d2d8ac6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Sesi kapatmak için dokunun."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ses denetimleri gösteriliyor. Kapatmak için hızlıca yukarı kaydırın."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ses denetimleri gizlendi"</string>
+ <string name="output_title" msgid="5355078100792942802">"Medya çıkışı"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefon çağrısı çıkışı"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Cihaz bulunamadı"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Cihaz bulunamadı. <xliff:g id="SERVICE">%1$s</xliff:g> hizmetini açmayı deneyin"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Kablosuz"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth ve Kablosuz"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistem Arayüzü Ayarlayıcısı"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Yerleşik pil yüzdesini göster"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Şarj olmazken durum çubuğu simgesinin içinde pil düzeyi yüzdesini göster"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Kapat"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kapatmak için aşağıya sürükleyin"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8fa1b72..23db95b 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -498,6 +498,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Двотональний багаточастотний аналоговий сигнал"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Спеціальні можливості"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Виклики"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Дзвінок"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Вібросигнал"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Без звуку"</string>
@@ -508,6 +509,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Торкніться, щоб вимкнути звук."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Показано регуляторів гучності: %s. Проведіть пальцем угору, щоб закрити."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Регулятори гучності сховано"</string>
+ <string name="output_title" msgid="5355078100792942802">"Вивід медіа-вмісту"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Вивід телефонного виклику"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Пристроїв не знайдено"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Пристроїв не знайдено. Увімкніть <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth і Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показувати заряд акумулятора у відсотках"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Показувати заряд акумулятора у відсотках в рядку стану, коли пристрій не заряджається"</string>
@@ -737,6 +745,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Розгорнути"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Згорнути"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Закрити"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перетягніть униз, щоб закрити"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 73fd5886..ad5ac98 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"بلوٹوتھ"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"دوہری ملٹی ٹون فریکوئنسی"</string>
<string name="stream_accessibility" msgid="301136219144385106">"ایکسیسبیلٹی"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"کالز"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"رِنگ کریں"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"وائبریٹ"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"خاموش کریں"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s والیوم کے کنٹرولز دکھائے جا رہے ہیں۔ برخاست کرنے کیلئے سوائپ کریں۔"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"والیوم کے کنٹرولز مخفی ہیں"</string>
+ <string name="output_title" msgid="5355078100792942802">"میڈیا آؤٹ پٹ"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"فون کال کا آؤٹ پٹ"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"کوئی آلہ نہیں ملا"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"کوئی آلہ نہیں ملا۔ <xliff:g id="SERVICE">%1$s</xliff:g> آن کر کے آزمائیں"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"بلوٹوتھ"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"بلوٹوتھ اور Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"سسٹم UI ٹیونر"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"سرایت کردہ بیٹری کی فیصد دکھائیں"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"جب چارج نہ ہو رہا ہو تو بیٹری کی سطح کی فیصد اسٹیٹس بار آئیکن کے اندر دکھائیں"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"بند کریں"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"برخاست کرنے کیلئے نیچے گھسیٹیں"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"مینو"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 55eb4fb..0db8ef2 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Ovozsiz qilish uchun ustiga bosing."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Ovoz balandligini boshqarish tugmalari ko‘rsatilgan: %s. Yopish uchun tepaga suring."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Ovoz balandligini boshqarish tugmalari yashirilgan"</string>
+ <string name="output_title" msgid="5355078100792942802">"Media chiqishi"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Telefon chaqiruvlari"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Hech qanday qurilma topilmadi"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Hech qanday qurilma topilmadi. <xliff:g id="SERVICE">%1$s</xliff:g> aloqasini yoqing."</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth va Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"SystemUI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Batareya foizini chiqarish"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Quvvat olmayotgan vaqtda batareya foizi holat qatorida chiqib turadi"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Yoyish"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Yig‘ish"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Yopish"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Yopish uchun pastga torting"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 551decf..75b18ca 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -505,6 +505,13 @@
<!-- no translation found for volume_dialog_accessibility_shown_message (1834631467074259998) -->
<skip />
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Các điều khiển âm lượng bị ẩn"</string>
+ <string name="output_title" msgid="5355078100792942802">"Đầu ra phương tiện"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Đầu ra cuộc gọi điệnt thoại"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Không tìm thấy thiết bị nào"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Không tìm thấy thiết bị nào. Hãy thử bật <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth và Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Bộ điều hướng giao diện người dùng hệ thống"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Hiển thị tỷ lệ phần trăm pin được nhúng"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Hiển thị tỷ lệ phần trăm mức pin bên trong biểu tượng thanh trạng thái khi không sạc"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Đóng"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kéo xuống để loại bỏ"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 2b64d86..16161ee 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -492,8 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"蓝牙"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"双音多频"</string>
<string name="stream_accessibility" msgid="301136219144385106">"无障碍"</string>
- <!-- no translation found for ring_toggle_title (3281244519428819576) -->
- <skip />
+ <string name="ring_toggle_title" msgid="3281244519428819576">"通话"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"响铃"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"振动"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"静音"</string>
@@ -504,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s。点按即可设为静音。"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"已显示%s音量控件。向上滑动即可关闭。"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"已隐藏音量控件"</string>
+ <string name="output_title" msgid="5355078100792942802">"媒体输出"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"通话输出"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"未找到任何设备"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"未找到任何设备。请尝试开启<xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"蓝牙"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"WLAN"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"蓝牙和 WLAN"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系统界面调节工具"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"嵌入式显示电池电量百分比 显示嵌入的电池电量百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"未充电时在状态栏图标内显示电池电量百分比"</string>
@@ -725,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"关闭"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖动即可关闭"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"菜单"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 382425d..e0ab7e4 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -505,6 +505,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s。輕按即可設為靜音。"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"已顯示 %s 音量控制項。向上快速滑動即可關閉。"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"已隱藏音量控制"</string>
+ <string name="output_title" msgid="5355078100792942802">"媒體輸出"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"通話輸出"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"找不到裝置"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"找不到裝置,請嘗試開啟<xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"藍牙"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"藍牙和 Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調諧器"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入的電池百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"非充電時,在狀態列圖示顯示電量百分比"</string>
@@ -726,6 +733,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"選單"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ef9ea43..2d43da8 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -503,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s。輕觸即可設為靜音。"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"已顯示 %s 個音量控制項。向上滑動即可關閉。"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"已隱藏音量控制項"</string>
+ <string name="output_title" msgid="5355078100792942802">"媒體輸出"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"通話輸出"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"找不到裝置"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"找不到裝置,請嘗試開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"藍牙"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"藍牙和 Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調整精靈"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入式電池百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"未充電時在狀態列圖示中顯示電量百分比"</string>
@@ -724,6 +731,8 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
+ <!-- no translation found for pip_phone_settings (8080777499521528521) -->
+ <skip />
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"選單"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index b3b26dc..e5bd3a9 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -492,6 +492,7 @@
<string name="stream_bluetooth_sco" msgid="2055645746402746292">"I-Bluetooth"</string>
<string name="stream_dtmf" msgid="2447177903892477915">"Ifrikhwensi yethoni engakuningi"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Ukufinyeleleka"</string>
+ <string name="ring_toggle_title" msgid="3281244519428819576">"Amakholi"</string>
<string name="volume_ringer_status_normal" msgid="4273142424125855384">"Khalisa"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Dlidlizela"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Thulisa"</string>
@@ -502,6 +503,13 @@
<string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Thepha ukuze uthulise."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s izilawuli zevolumu ziyaboniswa. Swayiphela phezulu ukuze ulahle."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Izilawuli zevolumi zifihliwe"</string>
+ <string name="output_title" msgid="5355078100792942802">"Okukhiphayo kwemidiya"</string>
+ <string name="output_calls_title" msgid="8717692905017206161">"Okukhiphayo kwekholi yefoni"</string>
+ <string name="output_none_found" msgid="5544982839808921091">"Awekho amadivayisi atholiwe"</string>
+ <string name="output_none_found_service_off" msgid="8631969668659757069">"Awekho amadivayisi atholiwe. Zama ukuvula i-<xliff:g id="SERVICE">%1$s</xliff:g>"</string>
+ <string name="output_service_bt" msgid="6224213415445509542">"I-Bluetooth"</string>
+ <string name="output_service_wifi" msgid="3749735218931825054">"I-Wi-Fi"</string>
+ <string name="output_service_bt_wifi" msgid="4486837869988770896">"I-Bluetooth ne-Wi-Fi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Isishuni se-UI yesistimu"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Bonisa amaphesenti ebhethri elinamathiselwe"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Bonisa amaphesenti eleveli yebhethri ngaphakathi kwesithonjana sebha yesimo uma kungashajwa"</string>
@@ -723,6 +731,7 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Nweba"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Nciphisa"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Vala"</string>
+ <string name="pip_phone_settings" msgid="8080777499521528521">"Izilungiselelo"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Hudulela phansi ukuze ucashise"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Imenyu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e313e86..b33f857 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -76,8 +76,11 @@
<!-- Vibration duration for GlowPadView used in SearchPanelView -->
<integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
+ <!-- Show mic or phone affordance on Keyguard -->
+ <bool name="config_keyguardShowLeftAffordance">false</bool>
+
<!-- Show camera affordance on Keyguard -->
- <bool name="config_keyguardShowCameraAffordance">true</bool>
+ <bool name="config_keyguardShowCameraAffordance">false</bool>
<!-- Whether we should use SRC drawing mode when drawing the scrim behind. If this flag is set,
we change the canvas opacity so libhwui doesn't call glClear on our surface, and then we
@@ -95,6 +98,12 @@
<bool name="config_dead_zone_flash">false</bool>
+ <!-- Whether to enable dimming navigation buttons when wallpaper is not visible, should be
+ enabled for OLED devices to reduce/prevent burn in on the navigation bar (because of the
+ black background and static button placements) and disabled for all other devices to
+ prevent wasting cpu cycles on the dimming animation -->
+ <bool name="config_navigation_bar_enable_auto_dim_no_visible_wallpaper">true</bool>
+
<!-- Whether QuickSettings is in a phone landscape -->
<bool name="quick_settings_wide">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 60e9ebf..a510c4a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -78,10 +78,10 @@
<dimen name="status_bar_connected_device_bt_indicator_size">17dp</dimen>
<!-- Height of a small notification in the status bar-->
- <dimen name="notification_min_height">100dp</dimen>
+ <dimen name="notification_min_height">106dp</dimen>
<!-- Increased height of a small notification in the status bar -->
- <dimen name="notification_min_height_increased">140dp</dimen>
+ <dimen name="notification_min_height_increased">146dp</dimen>
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
@@ -90,7 +90,7 @@
<dimen name="notification_min_height_before_p">92dp</dimen>
<!-- Height of a large notification in the status bar -->
- <dimen name="notification_max_height">292dp</dimen>
+ <dimen name="notification_max_height">294dp</dimen>
<!-- Height of an ambient notification on ambient display -->
<dimen name="notification_ambient_height">400dp</dimen>
@@ -102,16 +102,13 @@
<dimen name="notification_max_heads_up_height_before_p">148dp</dimen>
<!-- Height of a heads up notification in the status bar -->
- <dimen name="notification_max_heads_up_height">156dp</dimen>
+ <dimen name="notification_max_heads_up_height">162dp</dimen>
<!-- Height of a heads up notification in the status bar -->
<dimen name="notification_max_heads_up_height_increased">188dp</dimen>
<!-- Side padding on the lockscreen on the side of notifications -->
- <dimen name="notification_lockscreen_side_paddings">8dp</dimen>
-
- <!-- Additional side padding for custom content if the app doesn't target P yet -->
- <dimen name="notification_content_custom_view_side_padding">@dimen/notification_lockscreen_side_paddings</dimen>
+ <dimen name="notification_side_paddings">4dp</dimen>
<!-- Height of a messaging notifications with actions at least. Not that this is an upper bound
and the notification won't use this much, but is measured with wrap_content -->
@@ -127,7 +124,7 @@
<dimen name="notification_min_interaction_height">40dp</dimen>
<!-- the padding of the shelf icon container -->
- <dimen name="shelf_icon_container_padding">21dp</dimen>
+ <dimen name="shelf_icon_container_padding">13dp</dimen>
<!-- The padding of a notification icon on top to the start of the notification. Used for custom
views where the distance can't be measured -->
@@ -148,6 +145,12 @@
<!-- The space around a notification menu item -->
<dimen name="notification_menu_icon_padding">20dp</dimen>
+ <!-- The veritical space around the buttons in the inline settings -->
+ <dimen name="notification_guts_button_spacing">20dp</dimen>
+
+ <!-- The height of the header in inline settings -->
+ <dimen name="notification_guts_header_height">24dp</dimen>
+
<!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
<dimen name="snooze_snackbar_min_height">56dp</dimen>
@@ -232,7 +235,7 @@
<dimen name="qs_footer_height">48dp</dimen>
<!-- The padding between the notifications and the quick settings container -->
- <dimen name="qs_notification_keyguard_padding">8dp</dimen>
+ <dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
<!-- Height of the status bar header bar when expanded -->
<dimen name="status_bar_header_height_expanded">124dp</dimen>
@@ -385,9 +388,6 @@
group. -->
<dimen name="notification_children_container_divider_height">@dimen/notification_divider_height</dimen>
- <!-- The height of the header for a container containing child notifications. -->
- <dimen name="notification_children_container_header_height">53dp</dimen>
-
<!-- The top margin for the notification children container in its non-expanded form. -->
<dimen name="notification_children_container_margin_top">@*android:dimen/notification_content_margin_top</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index dd31365..fed97c5 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -86,10 +86,6 @@
<item type="id" name="top_roundess_animator_start_tag"/>
<item type="id" name="top_roundess_animator_end_tag"/>
- <item type="id" name="side_padding_animator_tag"/>
- <item type="id" name="side_padding_animator_start_tag"/>
- <item type="id" name="side_padding_animator_end_tag"/>
-
<!-- Accessibility actions for the notification menu -->
<item type="id" name="action_snooze_undo"/>
<item type="id" name="action_snooze_shorter"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 98537a1..a19917d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1445,38 +1445,22 @@
<string name="notification_header_default_channel">Notifications</string>
<!-- Notification Inline Controls: Shown when a channel's notifications are currently blocked -->
- <string name="notification_channel_disabled">You won\'t get these notifications anymore</string>
+ <string name="notification_channel_disabled">You won\'t see these notifications anymore</string>
- <!-- Notification: Control panel: Label that shows how many channels are included in this bundle
- of notifications. Replaces the channel name and only appears when there is more than one channel. -->
- <string name="notification_num_channels"> <xliff:g id="number">%d</xliff:g> notification categories</string>
+ <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
+ <string name="inline_keep_showing">Keep showing these notifications?</string>
- <!-- Notification: Control panel: Label that shows when an app has not upgraded to use channels.
- Hints that the user's only option is to block all of the app's notifications. -->
- <string name="notification_default_channel_desc">This app doesn\'t have notification categories</string>
+ <!-- Notification inline controls: block notifications button -->
+ <string name="inline_stop_button">Stop notifications</string>
+
+ <!-- Notification inline controls: keep getting notifications button -->
+ <string name="inline_keep_button">Keep showing</string>
+
+ <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
+ <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
<!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
- <string name="notification_unblockable_desc">Notifications from this app can\'t be turned off</string>
-
- <!-- Notification: Control panel: Label that shows how many channels this application has
- defined, describing the current notification channel as "1 out of n notification categories from this app". -->
- <plurals name="notification_num_channels_desc">
- <item quantity="one">1 out of <xliff:g id="number">%s</xliff:g> notification category from this app</item>
- <item quantity="other">1 out of <xliff:g id="number">%s</xliff:g> notification categories from this app</item>
- </plurals>
-
- <!-- Notification: Control panel: For bundles of notifications, this label that lists the
- channels used by the contained notifications. The first two channels are listed by name,
- followed by "and N others"
- Example: "Friend requests, Friend confirmations"
- Example: "Friend requests, Friend confirmations, and 1 other"
- Example: "Friend requests, Friend confirmations, and 2 others"
- -->
- <string name="notification_channels_list_desc_2"><xliff:g id="channel_name_1">%1$s</xliff:g>, <xliff:g id="channel_name_2">%2$s</xliff:g></string>
- <plurals name="notification_channels_list_desc_2_and_others">
- <item quantity="one"><xliff:g id="channel_name_1">%1$s</xliff:g>, <xliff:g id="channel_name_2">%2$s</xliff:g>, and <xliff:g id="number">%3$d</xliff:g> other</item>
- <item quantity="other"><xliff:g id="channel_name_1">%1$s</xliff:g>, <xliff:g id="channel_name_2">%2$s</xliff:g>, and <xliff:g id="number">%3$d</xliff:g> others</item>
- </plurals>
+ <string name="notification_unblockable_desc">These notifications can\'t be turned off</string>
<!-- Notification: Control panel: Accessibility description for expanded inline controls view, used
to control settings about notifications related to the current notification. -->
@@ -1488,16 +1472,15 @@
or disable notifications from this channel -->
<string name="notification_channel_switch_accessibility">Allow notifications from this channel</string>
<!-- Notification: Control panel: Label for button that launches notification settings. Used
- when this app has defined more than a single channel for notifications. -->
- <string name="notification_all_categories">All Categories</string>
- <!-- Notification: Control panel: Label for button that launches notification settings. Used
when this app has only defined a single channel for notifications. -->
<string name="notification_more_settings">More settings</string>
<!-- Notification: Control panel: Label for a link that launches notification settings in the
app that sent the notification. -->
- <string name="notification_app_settings">Customize: <xliff:g id="sub_category" example="Work chats">%1$s</xliff:g></string>
+ <string name="notification_app_settings">Customize</string>
<!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
<string name="notification_done">Done</string>
+ <!-- Notification: inline controls: undo block button -->
+ <string name="inline_undo">Undo</string>
<!-- Notification: Menu row: Content description for menu items. [CHAR LIMIT=NONE] -->
<string name="notification_menu_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> <xliff:g id="menu_description" example="notification controls">%2$s</xliff:g></string>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index 13c48d0..45d1aad8 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -268,6 +268,18 @@
}
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+
+ // Only show marquee when visible
+ if (visibility == VISIBLE) {
+ setEllipsize(TextUtils.TruncateAt.MARQUEE);
+ } else {
+ setEllipsize(TextUtils.TruncateAt.END);
+ }
+ }
+
/**
* Top-level function for creating carrier text. Makes text based on simState, PLMN
* and SPN as well as device capabilities, such as being emergency call capable.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index b8adb6a..8135c61 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -26,6 +26,9 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.Settings;
+import android.text.Layout;
+import android.text.TextUtils;
+import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -40,6 +43,7 @@
import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.tuner.TunerService;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
@@ -129,7 +133,20 @@
android.app.slice.SliceItem.FORMAT_TEXT,
new String[]{android.app.slice.Slice.HINT_TITLE},
null /* nonHints */);
- mTitle.setText(mainTitle.getText());
+ CharSequence title = mainTitle.getText();
+ mTitle.setText(title);
+
+ // Check if we're already ellipsizing the text.
+ // We're going to figure out the best possible line break if not.
+ Layout layout = mTitle.getLayout();
+ if (layout != null){
+ final int lineCount = layout.getLineCount();
+ if (lineCount > 0) {
+ if (layout.getEllipsisCount(lineCount - 1) == 0) {
+ mTitle.setText(findBestLineBreak(title));
+ }
+ }
+ }
}
mClickActions.clear();
@@ -195,6 +212,46 @@
mListener.accept(mHasHeader);
}
+ /**
+ * Breaks a string in 2 lines where both have similar character count
+ * but first line is always longer.
+ *
+ * @param charSequence Original text.
+ * @return Optimal string.
+ */
+ private CharSequence findBestLineBreak(CharSequence charSequence) {
+ if (TextUtils.isEmpty(charSequence)) {
+ return charSequence;
+ }
+
+ String source = charSequence.toString();
+ // Ignore if there is only 1 word,
+ // or if line breaks were manually set.
+ if (source.contains("\n") || !source.contains(" ")) {
+ return source;
+ }
+
+ final String[] words = source.split(" ");
+ final StringBuilder optimalString = new StringBuilder(source.length());
+ int current = 0;
+ while (optimalString.length() < source.length() - optimalString.length()) {
+ optimalString.append(words[current]);
+ if (current < words.length - 1) {
+ optimalString.append(" ");
+ }
+ current++;
+ }
+ optimalString.append("\n");
+ for (int i = current; i < words.length; i++) {
+ optimalString.append(words[i]);
+ if (current < words.length - 1) {
+ optimalString.append(" ");
+ }
+ }
+
+ return optimalString.toString();
+ }
+
public void setDark(float darkAmount) {
mDarkAmount = darkAmount;
updateTextColors();
@@ -287,6 +344,9 @@
setPadding(horizontalPadding, 0, horizontalPadding, 0);
setCompoundDrawablePadding((int) context.getResources()
.getDimension(R.dimen.widget_icon_padding));
+ setMaxWidth(KeyguardSliceView.this.getWidth() / 2);
+ setMaxLines(1);
+ setEllipsize(TruncateAt.END);
}
public void setHasDivider(boolean hasDivider) {
diff --git a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java
index 6aa465c..a102260 100644
--- a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java
+++ b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java
@@ -24,6 +24,7 @@
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
+import android.graphics.PorterDuff;
import android.graphics.Region;
import android.os.Handler;
import android.os.Looper;
@@ -114,10 +115,9 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mBounds.reset();
if (insets.getDisplayCutout() != null) {
insets.getDisplayCutout().getBounds().getBoundaryPath(mBounds);
- } else {
- mBounds.reset();
}
invalidate();
return insets.consumeDisplayCutout();
@@ -126,7 +126,7 @@
@Override
protected void onDraw(Canvas canvas) {
if (!mBounds.isEmpty()) {
- mPaint.setColor(Color.DKGRAY);
+ mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(mBounds, mPaint);
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 22922e7..a7d1f0d 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -146,6 +146,7 @@
filter.addDataScheme("package");
filter.addDataSchemeSpecificPart(mLauncherComponentName.getPackageName(),
PatternMatcher.PATTERN_LITERAL);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
mContext.registerReceiver(mLauncherAddedReceiver, filter);
}
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
index b15b79f..6f7a270 100644
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
@@ -163,6 +163,7 @@
| WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
lp.setTitle("RoundedOverlay");
lp.gravity = Gravity.TOP;
+ lp.flags2 |= WindowManager.LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA;
return lp;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index b352ec9..75f1b50 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -16,6 +16,8 @@
package com.android.systemui.doze;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+
import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
@@ -79,6 +81,11 @@
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
case DOZE_AOD:
+ if (oldState == DOZE_AOD_PAUSED) {
+ mHost.dozeTimeTick();
+ }
+ scheduleTimeTick();
+ break;
case DOZE_AOD_PAUSING:
scheduleTimeTick();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index bef1aff..9883da6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
+import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.quicksettings.Tile;
@@ -82,6 +83,7 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_AIRPLANE_MODE);
final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue();
final boolean airplaneMode = value != 0;
state.value = airplaneMode;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index c35f591..8bdbf28 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -101,6 +101,9 @@
// state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
state.value = locationEnabled;
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_SHARE_LOCATION);
+ if (state.disabledByPolicy == false) {
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_LOCATION_MODE);
+ }
state.icon = mIcon;
state.slash.isSlashed = !state.value;
if (locationEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index ff0357a..e59c703 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -931,13 +931,6 @@
}
@Override
- public void setCurrentSidePaddings(float currentSidePaddings) {
- super.setCurrentSidePaddings(currentSidePaddings);
- mBackgroundNormal.setCurrentSidePaddings(currentSidePaddings);
- mBackgroundDimmed.setCurrentSidePaddings(currentSidePaddings);
- }
-
- @Override
protected boolean childNeedsClipping(View child) {
if (child instanceof NotificationBackgroundView && isClippingNeeded()) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f53eb48..d1e6dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -2362,16 +2362,15 @@
NotificationContentView contentView = (NotificationContentView) child;
if (isClippingNeeded()) {
return true;
- } else if (!hasNoRoundingAndNoPadding() && contentView.shouldClipToSidePaddings()) {
+ } else if (!hasNoRounding() && contentView.shouldClipToRounding()) {
return true;
}
} else if (child == mChildrenContainer) {
- if (isClippingNeeded() || ((isGroupExpanded() || isGroupExpansionChanging())
- && getClipBottomAmount() != 0.0f && getCurrentBottomRoundness() != 0.0f)) {
+ if (isClippingNeeded() || !hasNoRounding()) {
return true;
}
} else if (child instanceof NotificationGuts) {
- return !hasNoRoundingAndNoPadding();
+ return !hasNoRounding();
}
return super.childNeedsClipping(child);
}
@@ -2401,9 +2400,8 @@
return super.getCustomClipPath(child);
}
- private boolean hasNoRoundingAndNoPadding() {
- return mCurrentSidePaddings == 0 && getCurrentBottomRoundness() == 0.0f
- && getCurrentTopRoundness() == 0.0f;
+ private boolean hasNoRounding() {
+ return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f;
}
public boolean isShowingAmbient() {
@@ -2418,20 +2416,6 @@
}
}
- @Override
- public void setCurrentSidePaddings(float currentSidePaddings) {
- if (mIsSummaryWithChildren) {
- List<ExpandableNotificationRow> notificationChildren =
- mChildrenContainer.getNotificationChildren();
- int size = notificationChildren.size();
- for (int i = 0; i < size; i++) {
- ExpandableNotificationRow row = notificationChildren.get(i);
- row.setCurrentSidePaddings(currentSidePaddings);
- }
- }
- super.setCurrentSidePaddings(currentSidePaddings);
- }
-
public static class NotificationViewState extends ExpandableViewState {
private final StackScrollState mOverallState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index db19d2f..66b3a75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -58,6 +58,7 @@
private static final Path EMPTY_PATH = new Path();
private final Rect mOutlineRect = new Rect();
+ private final Path mClipPath = new Path();
private boolean mCustomOutline;
private float mOutlineAlpha = -1f;
private float mOutlineRadius;
@@ -69,13 +70,14 @@
private float mBottomRoundness;
private float mTopRoundness;
private int mBackgroundTop;
- protected int mCurrentSidePaddings;
/**
* {@code true} if the children views of the {@link ExpandableOutlineView} are translated when
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
*/
protected boolean mShouldTranslateContents;
+ private boolean mClipRoundedToClipTopAmount;
+ private float mDistanceToTopRoundness = -1;
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@Override
@@ -83,9 +85,9 @@
if (!mCustomOutline && mCurrentTopRoundness == 0.0f
&& mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners) {
int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
- int left = Math.max(translation + mCurrentSidePaddings, mCurrentSidePaddings);
+ int left = Math.max(translation, 0);
int top = mClipTopAmount + mBackgroundTop;
- int right = getWidth() - mCurrentSidePaddings + Math.min(translation, 0);
+ int right = getWidth() + Math.min(translation, 0);
int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
outline.setRect(left, top, right, bottom);
} else {
@@ -115,9 +117,9 @@
if (!mCustomOutline) {
int translation = mShouldTranslateContents && !ignoreTranslation
? (int) getTranslation() : 0;
- left = Math.max(translation + mCurrentSidePaddings, mCurrentSidePaddings);
+ left = Math.max(translation, 0);
top = mClipTopAmount + mBackgroundTop;
- right = getWidth() - mCurrentSidePaddings + Math.min(translation, 0);
+ right = getWidth() + Math.min(translation, 0);
bottom = Math.max(getActualHeight(), top);
int intersectBottom = Math.max(getActualHeight() - mClipBottomAmount, top);
if (bottom != intersectBottom) {
@@ -135,8 +137,6 @@
top = mOutlineRect.top;
right = mOutlineRect.right;
bottom = mOutlineRect.bottom;
- left = Math.max(mCurrentSidePaddings, left);
- right = Math.min(getWidth() - mCurrentSidePaddings, right);
}
height = bottom - top;
if (height == 0) {
@@ -162,15 +162,8 @@
return roundedRectPath;
}
- protected Path getRoundedRectPath(int left, int top, int right, int bottom, float topRoundness,
- float bottomRoundness) {
- getRoundedRectPath(left, top, right, bottom, topRoundness, bottomRoundness,
- mTmpPath);
- return mTmpPath;
- }
-
- private void getRoundedRectPath(int left, int top, int right, int bottom, float topRoundness,
- float bottomRoundness, Path outPath) {
+ public static void getRoundedRectPath(int left, int top, int right, int bottom,
+ float topRoundness, float bottomRoundness, Path outPath) {
outPath.reset();
int width = right - left;
float topRoundnessX = topRoundness;
@@ -207,20 +200,50 @@
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
canvas.save();
+ Path intersectPath = null;
+ if (mClipRoundedToClipTopAmount) {
+ int left = 0;
+ int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
+ int right = getWidth();
+ int bottom = (int) Math.max(getActualHeight() - mClipBottomAmount,
+ top + mOutlineRadius);
+ ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
+ 0.0f,
+ mClipPath);
+ intersectPath = mClipPath;
+ }
+ boolean clipped = false;
if (childNeedsClipping(child)) {
Path clipPath = getCustomClipPath(child);
if (clipPath == null) {
clipPath = getClipPath();
}
if (clipPath != null) {
+ if (intersectPath != null) {
+ clipPath.op(intersectPath, Path.Op.INTERSECT);
+ }
canvas.clipPath(clipPath);
+ clipped = true;
}
}
+ if (!clipped && intersectPath != null) {
+ canvas.clipPath(intersectPath);
+ }
boolean result = super.drawChild(canvas, child, drawingTime);
canvas.restore();
return result;
}
+ @Override
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ super.setDistanceToTopRoundness(distanceToTopRoundness);
+ if (distanceToTopRoundness != mDistanceToTopRoundness) {
+ mClipRoundedToClipTopAmount = distanceToTopRoundness >= 0;
+ mDistanceToTopRoundness = distanceToTopRoundness;
+ invalidate();
+ }
+ }
+
protected boolean childNeedsClipping(View child) {
return false;
}
@@ -395,10 +418,4 @@
public Path getCustomClipPath(View child) {
return null;
}
-
- public void setCurrentSidePaddings(float currentSidePaddings) {
- mCurrentSidePaddings = (int) currentSidePaddings;
- invalidateOutline();
- invalidate();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index f762513..eafa825 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -130,6 +130,14 @@
}
}
+ /**
+ * Set the distance to the top roundness, from where we should start clipping a value above
+ * or equal to 0 is the effective distance, and if a value below 0 is received, there should
+ * be no clipping.
+ */
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ }
+
public void setActualHeight(int actualHeight) {
setActualHeight(actualHeight, true /* notifyListeners */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 68cf51c..45b35d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -41,7 +41,6 @@
private int mClipBottomAmount;
private int mTintColor;
private float[] mCornerRadii = new float[8];
- private int mCurrentSidePaddings;
private boolean mBottomIsRounded;
private int mBackgroundTop;
private boolean mBottomAmountClips = true;
@@ -68,8 +67,7 @@
if (mBottomIsRounded && mBottomAmountClips) {
bottom -= mClipBottomAmount;
}
- drawable.setBounds(mCurrentSidePaddings, mBackgroundTop,
- getWidth() - mCurrentSidePaddings, bottom);
+ drawable.setBounds(0, mBackgroundTop, getWidth(), bottom);
drawable.draw(canvas);
}
}
@@ -206,11 +204,6 @@
}
}
- public void setCurrentSidePaddings(float currentSidePaddings) {
- mCurrentSidePaddings = (int) currentSidePaddings;
- invalidate();
- }
-
public void setBackgroundTop(int backgroundTop) {
mBackgroundTop = backgroundTop;
invalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 39c2131..c73e548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -136,7 +136,6 @@
private int mClipBottomAmount;
private boolean mIsLowPriority;
private boolean mIsContentExpandable;
- private int mCustomViewSidePaddings;
public NotificationContentView(Context context, AttributeSet attrs) {
@@ -150,8 +149,6 @@
R.dimen.min_notification_layout_height);
mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
- mCustomViewSidePaddings = getResources().getDimensionPixelSize(
- R.dimen.notification_content_custom_view_side_padding);
}
public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight,
@@ -391,22 +388,6 @@
mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
- updateMargins(child);
- }
-
- private void updateMargins(View child) {
- if (child == null) {
- return;
- }
- NotificationViewWrapper wrapper = getWrapperForView(child);
- boolean isCustomView = wrapper instanceof NotificationCustomViewWrapper;
- boolean needsMargins = isCustomView &&
- child.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P;
- int padding = needsMargins ? mCustomViewSidePaddings : 0;
- MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
- layoutParams.setMarginStart(padding);
- layoutParams.setMarginEnd(padding);
- child.setLayoutParams(layoutParams);
}
private NotificationViewWrapper getWrapperForView(View child) {
@@ -456,7 +437,6 @@
mExpandedChild = child;
mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
- updateMargins(child);
}
public void setHeadsUpChild(View child) {
@@ -490,7 +470,6 @@
mHeadsUpChild = child;
mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
- updateMargins(child);
}
public void setAmbientChild(View child) {
@@ -1510,19 +1489,19 @@
return false;
}
- public boolean shouldClipToSidePaddings() {
- boolean needsPaddings = shouldClipToSidePaddings(getVisibleType());
+ public boolean shouldClipToRounding() {
+ boolean needsPaddings = shouldClipToRounding(getVisibleType());
if (mUserExpanding) {
- needsPaddings |= shouldClipToSidePaddings(mTransformationStartVisibleType);
+ needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType);
}
return needsPaddings;
}
- private boolean shouldClipToSidePaddings(int visibleType) {
+ private boolean shouldClipToRounding(int visibleType) {
NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
if (visibleWrapper == null) {
return false;
}
- return visibleWrapper.shouldClipToSidePaddings();
+ return visibleWrapper.shouldClipToRounding();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
index 87ad6f6b..441c184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
@@ -229,10 +229,9 @@
}
}
try {
- info.bindNotification(pmUser, iNotificationManager, pkg, new ArrayList(channels),
- row.getEntry().channel.getImportance(), sbn, onSettingsClick,
- onAppSettingsClick, onDoneClick, mCheckSaveListener,
- mNonBlockablePkgs);
+ info.bindNotification(pmUser, iNotificationManager, pkg, row.getEntry().channel,
+ channels.size(), sbn, mCheckSaveListener, onSettingsClick,
+ onAppSettingsClick, mNonBlockablePkgs);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 4301817..1127075 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -128,6 +128,7 @@
mComparators.add(HeaderProcessor.forTextView(mRow,
com.android.internal.R.id.header_text));
mDividers.add(com.android.internal.R.id.header_text_divider);
+ mDividers.add(com.android.internal.R.id.header_text_secondary_divider);
mDividers.add(com.android.internal.R.id.time_divider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 8d1bb5f..6279fdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -18,6 +18,10 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -38,12 +42,12 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import java.lang.IllegalArgumentException;
@@ -57,25 +61,37 @@
private static final String TAG = "InfoGuts";
private INotificationManager mINotificationManager;
+ private PackageManager mPm;
+
private String mPkg;
private String mAppName;
private int mAppUid;
- private List<NotificationChannel> mNotificationChannels;
+ private int mNumNotificationChannels;
private NotificationChannel mSingleNotificationChannel;
- private boolean mIsSingleDefaultChannel;
- private StatusBarNotification mSbn;
private int mStartingUserImportance;
+ private int mChosenImportance;
+ private boolean mIsSingleDefaultChannel;
+ private boolean mNonblockable;
+ private StatusBarNotification mSbn;
+ private AnimatorSet mExpandAnimation;
- private TextView mNumChannelsView;
- private View mChannelDisabledView;
- private TextView mSettingsLinkView;
- private Switch mChannelEnabledSwitch;
private CheckSaveListener mCheckSaveListener;
+ private OnSettingsClickListener mOnSettingsClickListener;
private OnAppSettingsClickListener mAppSettingsClickListener;
- private PackageManager mPm;
-
private NotificationGuts mGutsContainer;
+ private OnClickListener mOnKeepShowing = v -> {
+ closeControls(v);
+ };
+
+ private OnClickListener mOnStopNotifications = v -> {
+ swapContent(false);
+ };
+
+ private OnClickListener mOnUndo = v -> {
+ swapContent(true);
+ };
+
public NotificationInfo(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -98,141 +114,93 @@
public void bindNotification(final PackageManager pm,
final INotificationManager iNotificationManager,
final String pkg,
- final List<NotificationChannel> notificationChannels,
- int startingUserImportance,
+ final NotificationChannel notificationChannel,
+ final int numChannels,
final StatusBarNotification sbn,
- OnSettingsClickListener onSettingsClick,
- OnAppSettingsClickListener onAppSettingsClick,
- OnClickListener onDoneClick,
- CheckSaveListener checkSaveListener,
+ final CheckSaveListener checkSaveListener,
+ final OnSettingsClickListener onSettingsClick,
+ final OnAppSettingsClickListener onAppSettingsClick,
final Set<String> nonBlockablePkgs)
throws RemoteException {
mINotificationManager = iNotificationManager;
mPkg = pkg;
- mNotificationChannels = notificationChannels;
- mCheckSaveListener = checkSaveListener;
+ mNumNotificationChannels = numChannels;
mSbn = sbn;
mPm = pm;
mAppSettingsClickListener = onAppSettingsClick;
- mStartingUserImportance = startingUserImportance;
mAppName = mPkg;
- Drawable pkgicon = null;
- CharSequence channelNameText = "";
- ApplicationInfo info = null;
- try {
- info = pm.getApplicationInfo(mPkg,
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DIRECT_BOOT_AWARE);
- if (info != null) {
- mAppUid = sbn.getUid();
- mAppName = String.valueOf(pm.getApplicationLabel(info));
- pkgicon = pm.getApplicationIcon(info);
- }
- } catch (PackageManager.NameNotFoundException e) {
- // app is gone, just show package name and generic icon
- pkgicon = pm.getDefaultActivityIcon();
- }
- ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+ mCheckSaveListener = checkSaveListener;
+ mOnSettingsClickListener = onSettingsClick;
+ mSingleNotificationChannel = notificationChannel;
+ mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
- int numTotalChannels = iNotificationManager.getNumNotificationChannelsForPackage(
+ int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
- if (mNotificationChannels.isEmpty()) {
+ if (mNumNotificationChannels == 0) {
throw new IllegalArgumentException("bindNotification requires at least one channel");
} else {
- if (mNotificationChannels.size() == 1) {
- mSingleNotificationChannel = mNotificationChannels.get(0);
- // Special behavior for the Default channel if no other channels have been defined.
- mIsSingleDefaultChannel =
- (mSingleNotificationChannel.getId()
- .equals(NotificationChannel.DEFAULT_CHANNEL_ID) &&
- numTotalChannels <= 1);
- } else {
- mSingleNotificationChannel = null;
- mIsSingleDefaultChannel = false;
- }
+ // Special behavior for the Default channel if no other channels have been defined.
+ mIsSingleDefaultChannel = mNumNotificationChannels == 1
+ && mSingleNotificationChannel.getId()
+ .equals(NotificationChannel.DEFAULT_CHANNEL_ID)
+ && numTotalChannels <= 1;
}
- boolean nonBlockable = false;
try {
final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
if (Utils.isSystemPackage(getResources(), pm, pkgInfo)) {
- final int numChannels = mNotificationChannels.size();
- for (int i = 0; i < numChannels; i++) {
- final NotificationChannel notificationChannel = mNotificationChannels.get(i);
- // If any of the system channels is not blockable, the bundle is nonblockable
- if (!notificationChannel.isBlockableSystem()) {
- nonBlockable = true;
- break;
- }
+ if (mSingleNotificationChannel != null
+ && !mSingleNotificationChannel.isBlockableSystem()) {
+ mNonblockable = true;
}
}
} catch (PackageManager.NameNotFoundException e) {
// unlikely.
}
if (nonBlockablePkgs != null) {
- nonBlockable |= nonBlockablePkgs.contains(pkg);
+ mNonblockable |= nonBlockablePkgs.contains(pkg);
}
+ mNonblockable |= (mNumNotificationChannels > 1);
- String channelsDescText;
- mNumChannelsView = findViewById(R.id.num_channels_desc);
- if (nonBlockable) {
- channelsDescText = mContext.getString(R.string.notification_unblockable_desc);
- } else if (mIsSingleDefaultChannel) {
- channelsDescText = mContext.getString(R.string.notification_default_channel_desc);
- } else {
- switch (mNotificationChannels.size()) {
- case 1:
- channelsDescText = String.format(mContext.getResources().getQuantityString(
- R.plurals.notification_num_channels_desc, numTotalChannels),
- numTotalChannels);
- break;
- case 2:
- channelsDescText = mContext.getString(
- R.string.notification_channels_list_desc_2,
- mNotificationChannels.get(0).getName(),
- mNotificationChannels.get(1).getName());
- break;
- default:
- final int numOthers = mNotificationChannels.size() - 2;
- channelsDescText = String.format(
- mContext.getResources().getQuantityString(
- R.plurals.notification_channels_list_desc_2_and_others,
- numOthers),
- mNotificationChannels.get(0).getName(),
- mNotificationChannels.get(1).getName(),
- numOthers);
+ bindHeader();
+ bindPrompt();
+ bindButtons();
+ }
+
+ private void bindHeader() throws RemoteException {
+ // Package name
+ Drawable pkgicon = null;
+ ApplicationInfo info;
+ try {
+ info = mPm.getApplicationInfo(mPkg,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (info != null) {
+ mAppUid = mSbn.getUid();
+ mAppName = String.valueOf(mPm.getApplicationLabel(info));
+ pkgicon = mPm.getApplicationIcon(info);
}
+ } catch (PackageManager.NameNotFoundException e) {
+ // app is gone, just show package name and generic icon
+ pkgicon = mPm.getDefaultActivityIcon();
}
- mNumChannelsView.setText(channelsDescText);
-
- if (mSingleNotificationChannel == null) {
- // Multiple channels don't use a channel name for the title.
- channelNameText = mContext.getString(R.string.notification_num_channels,
- mNotificationChannels.size());
- } else if (mIsSingleDefaultChannel || nonBlockable) {
- // If this is the default channel or the app is unblockable,
- // don't use our channel-specific text.
- channelNameText = mContext.getString(R.string.notification_header_default_channel);
- } else {
- channelNameText = mSingleNotificationChannel.getName();
- }
+ ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
((TextView) findViewById(R.id.pkgname)).setText(mAppName);
- ((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
// Set group information if this channel has an associated group.
CharSequence groupName = null;
if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
final NotificationChannelGroup notificationChannelGroup =
- iNotificationManager.getNotificationChannelGroupForPackage(
- mSingleNotificationChannel.getGroup(), pkg, mAppUid);
+ mINotificationManager.getNotificationChannelGroupForPackage(
+ mSingleNotificationChannel.getGroup(), mPkg, mAppUid);
if (notificationChannelGroup != null) {
groupName = notificationChannelGroup.getName();
}
}
- TextView groupNameView = ((TextView) findViewById(R.id.group_name));
- TextView groupDividerView = ((TextView) findViewById(R.id.pkg_group_divider));
+ TextView groupNameView = findViewById(R.id.group_name);
+ TextView groupDividerView = findViewById(R.id.pkg_group_divider);
if (groupName != null) {
groupNameView.setText(groupName);
groupNameView.setVisibility(View.VISIBLE);
@@ -242,53 +210,55 @@
groupDividerView.setVisibility(View.GONE);
}
- bindButtons(nonBlockable);
-
- // Top-level importance group
- mChannelDisabledView = findViewById(R.id.channel_disabled);
- updateSecondaryText();
-
// Settings button.
- final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
- if (mAppUid >= 0 && onSettingsClick != null) {
+ final View settingsButton = findViewById(R.id.info);
+ if (mAppUid >= 0 && mOnSettingsClickListener != null) {
settingsButton.setVisibility(View.VISIBLE);
final int appUidF = mAppUid;
settingsButton.setOnClickListener(
(View view) -> {
- onSettingsClick.onClick(view, mSingleNotificationChannel, appUidF);
+ mOnSettingsClickListener.onClick(view,
+ mNumNotificationChannels > 1 ? null : mSingleNotificationChannel,
+ appUidF);
});
- if (numTotalChannels <= 1 || nonBlockable) {
- settingsButton.setText(R.string.notification_more_settings);
- } else {
- settingsButton.setText(R.string.notification_all_categories);
- }
} else {
settingsButton.setVisibility(View.GONE);
}
+ }
- // Done button.
- final TextView doneButton = (TextView) findViewById(R.id.done);
- doneButton.setText(R.string.notification_done);
- doneButton.setOnClickListener(onDoneClick);
+ private void bindPrompt() {
+ final TextView channelName = findViewById(R.id.channel_name);
+ final TextView blockPrompt = findViewById(R.id.block_prompt);
+ if (mNonblockable) {
+ if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
+ channelName.setVisibility(View.GONE);
+ } else {
+ channelName.setText(mSingleNotificationChannel.getName());
+ }
- // Optional settings link
- updateAppSettingsLink();
+ blockPrompt.setText(R.string.notification_unblockable_desc);
+ } else {
+ if (mIsSingleDefaultChannel || mNumNotificationChannels > 1) {
+ channelName.setVisibility(View.GONE);
+ blockPrompt.setText(R.string.inline_keep_showing_app);
+ } else {
+ channelName.setText(mSingleNotificationChannel.getName());
+ blockPrompt.setText(R.string.inline_keep_showing);
+ }
+ }
}
private boolean hasImportanceChanged() {
- return mSingleNotificationChannel != null &&
- mChannelEnabledSwitch != null &&
- mStartingUserImportance != getSelectedImportance();
+ return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
}
private void saveImportance() {
- if (!hasImportanceChanged()) {
+ if (mNonblockable || !hasImportanceChanged()) {
return;
}
- final int selectedImportance = getSelectedImportance();
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
- selectedImportance - mStartingUserImportance);
- mSingleNotificationChannel.setImportance(selectedImportance);
+ mChosenImportance - mStartingUserImportance);
+ mSingleNotificationChannel.setImportance(mChosenImportance);
mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
try {
mINotificationManager.updateNotificationChannelForPackage(
@@ -298,30 +268,78 @@
}
}
- private int getSelectedImportance() {
- if (!mChannelEnabledSwitch.isChecked()) {
- return IMPORTANCE_NONE;
+ private void bindButtons() {
+ View block = findViewById(R.id.block);
+ block.setOnClickListener(mOnStopNotifications);
+ TextView keep = findViewById(R.id.keep);
+ keep.setOnClickListener(mOnKeepShowing);
+ findViewById(R.id.undo).setOnClickListener(mOnUndo);
+
+ if (mNonblockable) {
+ keep.setText(R.string.notification_done);
+ block.setVisibility(GONE);
+ }
+
+ // app settings link
+ TextView settingsLinkView = findViewById(R.id.app_settings);
+ Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
+ mSbn.getId(), mSbn.getTag());
+ if (settingsIntent != null
+ && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
+ settingsLinkView.setVisibility(View.VISIBLE);
+ settingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
+ mSbn.getNotification().getSettingsText()));
+ settingsLinkView.setOnClickListener((View view) -> {
+ mAppSettingsClickListener.onClick(view, settingsIntent);
+ });
} else {
- return mStartingUserImportance;
+ settingsLinkView.setVisibility(View.GONE);
}
}
- private void bindButtons(final boolean nonBlockable) {
- // Enabled Switch
- mChannelEnabledSwitch = (Switch) findViewById(R.id.channel_enabled_switch);
- mChannelEnabledSwitch.setChecked(
- mStartingUserImportance != IMPORTANCE_NONE);
- final boolean visible = !nonBlockable && mSingleNotificationChannel != null;
- mChannelEnabledSwitch.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ private void swapContent(boolean showPrompt) {
+ if (mExpandAnimation != null) {
+ mExpandAnimation.cancel();
+ }
- // Callback when checked.
- mChannelEnabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
- if (mGutsContainer != null) {
- mGutsContainer.resetFalsingCheck();
+ if (showPrompt) {
+ mChosenImportance = mStartingUserImportance;
+ } else {
+ mChosenImportance = IMPORTANCE_NONE;
+ }
+
+ View prompt = findViewById(R.id.prompt);
+ View confirmation = findViewById(R.id.confirmation);
+ ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
+ prompt.getAlpha(), showPrompt ? 1f : 0f);
+ promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
+ confirmation.getAlpha(), showPrompt ? 0f : 1f);
+ confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+
+ prompt.setVisibility(showPrompt ? VISIBLE : GONE);
+ confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+
+ mExpandAnimation = new AnimatorSet();
+ mExpandAnimation.playTogether(promptAnim, confirmAnim);
+ mExpandAnimation.setDuration(150);
+ mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+ boolean cancelled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cancelled = true;
}
- updateSecondaryText();
- updateAppSettingsLink();
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!cancelled) {
+ prompt.setVisibility(showPrompt ? VISIBLE : GONE);
+ confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+ }
+ }
});
+ mExpandAnimation.start();
}
@Override
@@ -339,35 +357,6 @@
}
}
- private void updateSecondaryText() {
- final boolean disabled = mSingleNotificationChannel != null &&
- getSelectedImportance() == IMPORTANCE_NONE;
- if (disabled) {
- mChannelDisabledView.setVisibility(View.VISIBLE);
- mNumChannelsView.setVisibility(View.GONE);
- } else {
- mChannelDisabledView.setVisibility(View.GONE);
- mNumChannelsView.setVisibility(mIsSingleDefaultChannel ? View.INVISIBLE : View.VISIBLE);
- }
- }
-
- private void updateAppSettingsLink() {
- mSettingsLinkView = findViewById(R.id.app_settings);
- Intent settingsIntent = getAppSettingsIntent(mPm, mPkg, mSingleNotificationChannel,
- mSbn.getId(), mSbn.getTag());
- if (settingsIntent != null && getSelectedImportance() != IMPORTANCE_NONE
- && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
- mSettingsLinkView.setVisibility(View.VISIBLE);
- mSettingsLinkView.setText(mContext.getString(R.string.notification_app_settings,
- mSbn.getNotification().getSettingsText()));
- mSettingsLinkView.setOnClickListener((View view) -> {
- mAppSettingsClickListener.onClick(view, settingsIntent);
- });
- } else {
- mSettingsLinkView.setVisibility(View.GONE);
- }
- }
-
private Intent getAppSettingsIntent(PackageManager pm, String packageName,
NotificationChannel channel, int id, String tag) {
Intent intent = new Intent(Intent.ACTION_MAIN)
@@ -390,6 +379,18 @@
return intent;
}
+ private void closeControls(View v) {
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+ }
+
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
@@ -397,7 +398,7 @@
@Override
public boolean willBeRemoved() {
- return mChannelEnabledSwitch != null && !mChannelEnabledSwitch.isChecked();
+ return hasImportanceChanged();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index b2604fe..037eeb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -176,8 +176,6 @@
final Resources res = mContext.getResources();
mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
- mSidePadding = res.getDimensionPixelSize(R.dimen.notification_lockscreen_side_paddings);
- mIconPadding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
mMenuItems.clear();
// Construct the menu items based on the notification
if (mParent != null && mParent.getStatusBarNotification() != null) {
@@ -498,8 +496,8 @@
final int count = mMenuContainer.getChildCount();
for (int i = 0; i < count; i++) {
final View v = mMenuContainer.getChildAt(i);
- final float left = mSidePadding + i * mHorizSpaceForIcon;
- final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1)) - mSidePadding;
+ final float left = i * mHorizSpaceForIcon;
+ final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
v.setX(showOnLeft ? left : right);
}
mOnLeft = showOnLeft;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 66682e4..0d22095 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -38,7 +38,6 @@
private final Paint mGreyPaint = new Paint();
private boolean mIsLegacy;
private int mLegacyColor;
- private boolean mBeforeP;
protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(ctx, view, row);
@@ -119,15 +118,7 @@
}
@Override
- public boolean shouldClipToSidePaddings() {
- // Before P we ensure that they are now drawing inside out content bounds since we inset
- // the view. If they target P, then we don't have that guarantee and we need to be safe.
- return !mBeforeP;
- }
-
- @Override
- public void onContentUpdated(ExpandableNotificationRow row) {
- super.onContentUpdated(row);
- mBeforeP = row.getEntry().targetSdk < Build.VERSION_CODES.P;
+ public boolean shouldClipToRounding() {
+ return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index 060e6d6..d7c08cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -62,7 +62,7 @@
}
@Override
- public boolean shouldClipToSidePaddings() {
+ public boolean shouldClipToRounding() {
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index e07112f..fd085d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -265,11 +265,6 @@
updateActionOffset();
}
- @Override
- public boolean shouldClipToSidePaddings() {
- return mActionsContainer != null && mActionsContainer.getVisibility() != View.GONE;
- }
-
private void updateActionOffset() {
if (mActionsContainer != null) {
// We should never push the actions higher than they are in the headsup view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 8a767bb..c71d604 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -195,7 +195,7 @@
return 0;
}
- public boolean shouldClipToSidePaddings() {
+ public boolean shouldClipToRounding() {
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 6d85fb3..fb3adf4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -25,12 +25,14 @@
import android.util.SparseBooleanArray;
import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
+import com.android.systemui.tuner.TunerService;
import java.io.PrintWriter;
-public class DozeParameters {
+public class DozeParameters implements TunerService.Tunable {
private static final int MAX_DURATION = 60 * 1000;
public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
@@ -40,10 +42,15 @@
private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
+ private boolean mDozeAlwaysOn;
+
public DozeParameters(Context context) {
mContext = context;
mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(context);
+
+ Dependency.get(TunerService.class).addTunable(this, Settings.Secure.DOZE_ALWAYS_ON,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
}
public void dump(PrintWriter pw) {
@@ -144,7 +151,7 @@
* @return {@code true} if enabled and available.
*/
public boolean getAlwaysOn() {
- return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ return mDozeAlwaysOn;
}
/**
@@ -207,6 +214,10 @@
return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
}
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ }
/**
* Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index df1ffda..46d9827 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -529,6 +529,13 @@
KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
startSwiping(targetView);
+
+ // Do not animate the circle expanding if the affordance isn't visible,
+ // otherwise the circle will be meaningless.
+ if (targetView.getVisibility() != View.VISIBLE) {
+ animate = false;
+ }
+
if (animate) {
fling(0, false, !left);
updateIcon(otherView, 0.0f, 0, true, false, true, false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index f058862..01b3b44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -822,8 +822,10 @@
@Override
public IconState getIcon() {
mLeftIsVoiceAssist = canLaunchVoiceAssist();
+ final boolean showAffordance =
+ getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
if (mLeftIsVoiceAssist) {
- mIconState.isVisible = mUserSetupComplete;
+ mIconState.isVisible = mUserSetupComplete && showAffordance;
if (mLeftAssistIcon == null) {
mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
} else {
@@ -832,7 +834,7 @@
mIconState.contentDescription = mContext.getString(
R.string.accessibility_voice_assist_button);
} else {
- mIconState.isVisible = mUserSetupComplete && isPhoneVisible();
+ mIconState.isVisible = mUserSetupComplete && showAffordance && isPhoneVisible();
mIconState.drawable = mContext.getDrawable(R.drawable.ic_phone_24dp);
mIconState.contentDescription = mContext.getString(
R.string.accessibility_phone_button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index bed6d82..6f636aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -47,8 +47,7 @@
/**
* Class to detect gestures on the navigation bar.
*/
-public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener
- implements TunerService.Tunable, GestureHelper {
+public class NavigationBarGestureHelper implements TunerService.Tunable, GestureHelper {
private static final String TAG = "NavBarGestureHelper";
private static final String KEY_DOCK_WINDOW_GESTURE = "overview_nav_bar_gesture";
@@ -72,11 +71,8 @@
private Context mContext;
private NavigationBarView mNavigationBarView;
private boolean mIsVertical;
- private boolean mIsRTL;
- private final GestureDetector mTaskSwitcherDetector;
private final int mScrollTouchSlop;
- private final int mMinFlingVelocity;
private final Matrix mTransformGlobalMatrix = new Matrix();
private final Matrix mTransformLocalMatrix = new Matrix();
private int mTouchDownX;
@@ -91,11 +87,8 @@
public NavigationBarGestureHelper(Context context) {
mContext = context;
- ViewConfiguration configuration = ViewConfiguration.get(context);
Resources r = context.getResources();
mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
- mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
- mTaskSwitcherDetector = new GestureDetector(context, this);
Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
}
@@ -112,7 +105,6 @@
public void setBarState(boolean isVertical, boolean isRTL) {
mIsVertical = isVertical;
- mIsRTL = isRTL;
}
private boolean proxyMotionEvents(MotionEvent event) {
@@ -161,11 +153,7 @@
case MotionEvent.ACTION_UP:
break;
}
- if (!proxyMotionEvents(event)) {
- // If we move more than a fixed amount, then start capturing for the
- // task switcher detector, disabled when proxying motion events to launcher service
- mTaskSwitcherDetector.onTouchEvent(event);
- }
+ proxyMotionEvents(event);
return result || (mDockWindowEnabled && interceptDockWindowEvent(event));
}
@@ -306,7 +294,7 @@
}
public boolean onTouchEvent(MotionEvent event) {
- boolean result = proxyMotionEvents(event) || mTaskSwitcherDetector.onTouchEvent(event);
+ boolean result = proxyMotionEvents(event);
if (mDockWindowEnabled) {
result |= handleDockWindowEvent(event);
}
@@ -314,29 +302,6 @@
}
@Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- float absVelX = Math.abs(velocityX);
- float absVelY = Math.abs(velocityY);
- boolean isValidFling = absVelX > mMinFlingVelocity &&
- mIsVertical ? (absVelY > absVelX) : (absVelX > absVelY);
- if (isValidFling && mRecentsComponent != null) {
- boolean showNext;
- if (!mIsRTL) {
- showNext = mIsVertical ? (velocityY < 0) : (velocityX < 0);
- } else {
- // In RTL, vertical is still the same, but horizontal is flipped
- showNext = mIsVertical ? (velocityY < 0) : (velocityX > 0);
- }
- if (showNext) {
- mRecentsComponent.showNextAffiliatedTask();
- } else {
- mRecentsComponent.showPrevAffiliatedTask();
- }
- }
- return true;
- }
-
- @Override
public void onTuningChanged(String key, String newValue) {
switch (key) {
case KEY_DOCK_WINDOW_GESTURE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index b81a3b0..bd6421c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -26,7 +26,6 @@
import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManagerGlobal;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
@@ -37,6 +36,7 @@
private final NavigationBarView mView;
private final IStatusBarService mBarService;
private final LightBarTransitionsController mLightTransitionsController;
+ private final boolean mAllowAutoDimWallpaperNotVisible;
private boolean mWallpaperVisible;
private boolean mLightsOut;
@@ -49,6 +49,8 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mLightTransitionsController = new LightBarTransitionsController(view.getContext(),
this::applyDarkIntensity);
+ mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
+ .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
Handler handler = Handler.getMain();
@@ -80,8 +82,8 @@
@Override
protected boolean isLightsOut(int mode) {
- return super.isLightsOut(mode) || (mAutoDim && !mWallpaperVisible
- && mode != MODE_WARNING);
+ return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim
+ && !mWallpaperVisible && mode != MODE_WARNING);
}
public LightBarTransitionsController getLightTransitionsController() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2796f0f..392581d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -199,8 +199,10 @@
}
}
- private final OverviewProxyListener mOverviewProxyListener =
- isConnected -> setSlippery(!isConnected);
+ private final OverviewProxyListener mOverviewProxyListener = isConnected -> {
+ setSlippery(!isConnected);
+ setDisabledFlags(mDisabledFlags, true);
+ };
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
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 f0bd1f9..32675d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -309,7 +309,7 @@
mIndicationBottomPadding = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_bottom_padding);
mQsNotificationTopPadding = getResources().getDimensionPixelSize(
- R.dimen.qs_notification_keyguard_padding);
+ R.dimen.qs_notification_padding);
}
public void updateResources() {
@@ -451,7 +451,8 @@
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
if (mStatusBarState != StatusBarState.KEYGUARD) {
- stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight;
+ stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
+ + mQsNotificationTopPadding;
mTopPaddingAdjustment = 0;
} else {
mClockPositionAlgorithm.setup(
@@ -1381,7 +1382,7 @@
mNotificationStackScroller.getIntrinsicPadding(),
mQsMaxExpansionHeight + mQsNotificationTopPadding);
} else {
- return mQsExpansionHeight;
+ return mQsExpansionHeight + mQsNotificationTopPadding;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index c0241e3..5505099 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -128,12 +128,11 @@
mDividerHeight = res.getDimensionPixelSize(
R.dimen.notification_children_container_divider_height);
mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
- mHeaderHeight = res.getDimensionPixelSize(
- R.dimen.notification_children_container_header_height);
mNotificationHeaderMargin = res.getDimensionPixelSize(
R.dimen.notification_children_container_margin_top);
mNotificatonTopPadding = res.getDimensionPixelSize(
R.dimen.notification_children_container_top_padding);
+ mHeaderHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
mCollapsedBottompadding = res.getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_bottom);
mEnableShadowOnChildNotifications =
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 369e7ff..167508a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -76,7 +76,6 @@
import com.android.systemui.statusbar.DismissView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableOutlineView;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationGuts;
@@ -86,10 +85,8 @@
import com.android.systemui.statusbar.NotificationSnooze;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -126,16 +123,7 @@
/**
* Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
*/
- private static final int INVALID_POINTER = -1;
- private static final AnimatableProperty SIDE_PADDINGS = AnimatableProperty.from(
- "sidePaddings",
- NotificationStackScrollLayout::setCurrentSidePadding,
- NotificationStackScrollLayout::getCurrentSidePadding,
- R.id.side_padding_animator_tag,
- R.id.side_padding_animator_end_tag,
- R.id.side_padding_animator_start_tag);
- private static final AnimationProperties SIDE_PADDING_PROPERTIES =
- new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ private static final int INVALID_POINTER = -1;;
private ExpandHelper mExpandHelper;
private NotificationSwipeHelper mSwipeHelper;
@@ -143,7 +131,6 @@
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
private final Path mBackgroundPath = new Path();
- private final float[] mBackgroundRadii = new float[8];
private final boolean mShouldDrawNotificationBackground;
private float mExpandedHeight;
@@ -174,7 +161,6 @@
private int mTopPadding;
private int mBottomMargin;
private int mBottomInset = 0;
- private float mCurrentSidePadding;
/**
* The algorithm which calculates the properties for our children
@@ -402,7 +388,6 @@
private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
private Runnable mAnimateScroll = this::animateScroll;
private int mCornerRadius;
- private int mLockscreenSidePaddings;
private int mSidePaddings;
public NotificationStackScrollLayout(Context context) {
@@ -440,8 +425,7 @@
res.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
updateWillNotDraw();
- mBackgroundPaint.setAntiAlias(true);
- mBackgroundPaint.setStyle(Paint.Style.FILL);
+ mBackgroundPaint.setAntiAlias(true);;
if (DEBUG) {
mDebugPaint = new Paint();
mDebugPaint.setColor(0xffff0000);
@@ -490,7 +474,8 @@
protected void onDraw(Canvas canvas) {
if (mShouldDrawNotificationBackground && !mAmbientState.isDark()
&& mCurrentBounds.top < mCurrentBounds.bottom) {
- canvas.drawPath(mBackgroundPath, mBackgroundPaint);
+ canvas.drawRoundRect(mSidePaddings, mCurrentBounds.top, getWidth() - mSidePaddings,
+ mCurrentBounds.bottom, mCornerRadius, mCornerRadius, mBackgroundPaint);
}
if (DEBUG) {
@@ -543,8 +528,7 @@
R.dimen.min_top_overscroll_to_qs);
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
- mLockscreenSidePaddings = res.getDimensionPixelSize(
- R.dimen.notification_lockscreen_side_paddings);
+ mSidePaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
mMinInteractionHeight = res.getDimensionPixelSize(
R.dimen.notification_min_interaction_height);
mCornerRadius = res.getDimensionPixelSize(
@@ -575,11 +559,15 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(width - mSidePaddings * 2,
+ MeasureSpec.getMode(widthMeasureSpec));
// We need to measure all children even the GONE ones, such that the heights are calculated
// correctly as they are used to calculate how many we can fit on the screen.
final int size = getChildCount();
for (int i = 0; i < size; i++) {
- measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
+ measureChild(getChildAt(i), childWidthSpec, heightMeasureSpec);
}
}
@@ -675,11 +663,32 @@
private void onPreDrawDuringAnimation() {
mShelf.updateAppearance();
+ updateClippingToTopRoundedCorner();
if (!mNeedsAnimation && !mChildrenUpdateRequested) {
updateBackground();
}
}
+ private void updateClippingToTopRoundedCorner() {
+ Float clipStart = (float) mTopPadding;
+ Float clipEnd = clipStart + mCornerRadius;
+ boolean first = true;
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+ float start = child.getTranslationY();
+ float end = start + Math.max(child.getActualHeight() - child.getClipBottomAmount(),
+ 0);
+ boolean clip = clipStart > start && clipStart < end
+ || clipEnd >= start && clipEnd <= end;
+ clip &= !(first && mOwnScrollY == 0);
+ child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0) : -1);
+ first = false;
+ }
+ }
+
private void updateScrollStateForAddedChildren() {
if (mChildrenToAddAnimated.isEmpty()) {
return;
@@ -2255,31 +2264,9 @@
mScrimController.setExcludedBackgroundArea(
mFadingOut || mParentNotFullyVisible || mAmbientState.isDark() || mIsClipped ? null
: mCurrentBounds);
- updateBackgroundPath();
invalidate();
}
- private void updateBackgroundPath() {
- mBackgroundPath.reset();
- float topRoundness = 0;
- if (mFirstVisibleBackgroundChild != null) {
- topRoundness = mFirstVisibleBackgroundChild.getCurrentBackgroundRadiusTop();
- }
- topRoundness = onKeyguard() ? mCornerRadius : topRoundness;
- float bottomRoundNess = mCornerRadius;
- mBackgroundRadii[0] = topRoundness;
- mBackgroundRadii[1] = topRoundness;
- mBackgroundRadii[2] = topRoundness;
- mBackgroundRadii[3] = topRoundness;
- mBackgroundRadii[4] = bottomRoundNess;
- mBackgroundRadii[5] = bottomRoundNess;
- mBackgroundRadii[6] = bottomRoundNess;
- mBackgroundRadii[7] = bottomRoundNess;
- mBackgroundPath.addRoundRect(mCurrentSidePadding, mCurrentBounds.top,
- getWidth() - mCurrentSidePadding, mCurrentBounds.bottom, mBackgroundRadii,
- Path.Direction.CCW);
- }
-
/**
* Update the background bounds to the new desired bounds
*/
@@ -2292,8 +2279,8 @@
mBackgroundBounds.left = mTempInt2[0];
mBackgroundBounds.right = mTempInt2[0] + getWidth();
}
- mBackgroundBounds.left += mCurrentSidePadding;
- mBackgroundBounds.right -= mCurrentSidePadding;
+ mBackgroundBounds.left += mSidePaddings;
+ mBackgroundBounds.right -= mSidePaddings;
if (!mIsExpanded) {
mBackgroundBounds.top = 0;
mBackgroundBounds.bottom = 0;
@@ -2902,8 +2889,7 @@
private void applyRoundedNess() {
if (mFirstVisibleBackgroundChild != null) {
- mFirstVisibleBackgroundChild.setTopRoundness(
- mStatusBarState == StatusBarState.KEYGUARD ? 1.0f : 0.0f,
+ mFirstVisibleBackgroundChild.setTopRoundness(1.0f,
mFirstVisibleBackgroundChild.isShown()
&& !mChildrenToAddAnimated.contains(mFirstVisibleBackgroundChild));
}
@@ -2912,7 +2898,6 @@
mLastVisibleBackgroundChild.isShown()
&& !mChildrenToAddAnimated.contains(mLastVisibleBackgroundChild));
}
- updateBackgroundPath();
invalidate();
}
@@ -2922,7 +2907,6 @@
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
updateChronometerForChild(child);
- updateCurrentSidePaddings(child);
}
private void updateHideSensitiveForChild(View child) {
@@ -3021,6 +3005,7 @@
mAnimationEvents.clear();
updateBackground();
updateViewShadows();
+ updateClippingToTopRoundedCorner();
} else {
applyCurrentState();
}
@@ -3714,6 +3699,7 @@
setAnimationRunning(false);
updateBackground();
updateViewShadows();
+ updateClippingToTopRoundedCorner();
}
private void updateViewShadows() {
@@ -4382,43 +4368,6 @@
public void setStatusBarState(int statusBarState) {
mStatusBarState = statusBarState;
mAmbientState.setStatusBarState(statusBarState);
- applyRoundedNess();
- updateSidePaddings();
- }
-
- private void updateSidePaddings() {
- int sidePaddings = mStatusBarState == StatusBarState.KEYGUARD ? mLockscreenSidePaddings : 0;
- if (sidePaddings != mSidePaddings) {
- boolean animate = isShown();
- mSidePaddings = sidePaddings;
- PropertyAnimator.setProperty(this, SIDE_PADDINGS, sidePaddings,
- SIDE_PADDING_PROPERTIES, animate);
- }
- }
-
- protected void setCurrentSidePadding(float sidePadding) {
- mCurrentSidePadding = sidePadding;
- updateBackground();
- applySidePaddingsToChildren();
- }
-
- private void applySidePaddingsToChildren() {
- for (int i = 0; i < getChildCount(); i++) {
- View view = getChildAt(i);
- updateCurrentSidePaddings(view);
- }
- }
-
- private void updateCurrentSidePaddings(View view) {
- if (!(view instanceof ExpandableOutlineView)) {
- return;
- }
- ExpandableOutlineView outlineView = (ExpandableOutlineView) view;
- outlineView.setCurrentSidePaddings(mCurrentSidePadding);
- }
-
- protected float getCurrentSidePadding() {
- return mCurrentSidePadding;
}
public void setExpandingVelocity(float expandingVelocity) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index e117969..0a3e34e 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -68,7 +68,6 @@
String appName = mResolveInfo.loadLabel(packageManager).toString();
final AlertController.AlertParams ap = mAlertParams;
- ap.mIcon = mResolveInfo.loadIcon(packageManager);
ap.mTitle = appName;
if (mDevice == null) {
ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName,
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 4606aee..238407a 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -90,7 +90,6 @@
String appName = aInfo.loadLabel(packageManager).toString();
final AlertController.AlertParams ap = mAlertParams;
- ap.mIcon = aInfo.loadIcon(packageManager);
ap.mTitle = appName;
if (mDevice == null) {
ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index d7c8010..7b91f14 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -413,6 +413,9 @@
Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, AudioManager.STREAM_RING,
mRingerIcon.getTag());
final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+ if (ss == null) {
+ return;
+ }
final boolean hasVibrator = mController.hasVibrator();
if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
if (hasVibrator) {
@@ -617,6 +620,9 @@
protected void updateRingerH() {
if (mState != null) {
final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+ if (ss == null) {
+ return;
+ }
switch (mState.ringerModeInternal) {
case AudioManager.RINGER_MODE_VIBRATE:
mRingerStatus.setText(R.string.volume_ringer_status_vibrate);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
index 3e6bd7e..2398fd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
@@ -61,7 +61,7 @@
@Override
public void dozeTimeTick() {
- throw new RuntimeException("not implemented");
+ // Nothing to do in here. Real host would just update the UI.
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 6721938..d77bf69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -16,11 +16,13 @@
package com.android.systemui.statusbar;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.any;
@@ -50,11 +52,11 @@
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
+import android.testing.PollingCheck;
import android.testing.UiThreadTest;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
-import android.widget.Switch;
import android.widget.TextView;
import com.android.systemui.R;
@@ -66,7 +68,6 @@
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -117,50 +118,31 @@
// Some test channels.
mNotificationChannel = new NotificationChannel(
- TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
+ TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW);
mDefaultNotificationChannel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
- NotificationManager.IMPORTANCE_LOW);
+ IMPORTANCE_LOW);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
}
- private CharSequence getStringById(int resId) {
- return mContext.getString(resId);
+ // TODO: if tests are taking too long replace this with something that makes the animation
+ // finish instantly.
+ private void waitForUndoButton() {
+ PollingCheck.waitFor(1000,
+ () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
}
-
- private CharSequence getNumChannelsDescString(int numChannels) {
- return String.format(
- mContext.getResources().getQuantityString(
- R.plurals.notification_num_channels_desc, numChannels),
- numChannels);
- }
-
- private CharSequence getChannelsListDescString(NotificationChannel... channels) {
- if (channels.length == 2) {
- return mContext.getString(R.string.notification_channels_list_desc_2,
- channels[0].getName(), channels[1].getName());
- } else {
- final int numOthers = channels.length - 2;
- return String.format(
- mContext.getResources().getQuantityString(
- R.plurals.notification_channels_list_desc_2_and_others, numOthers),
- channels[0].getName(), channels[1].getName(), numOthers);
- }
- }
-
- private CharSequence getNumChannelsString(int numChannels) {
- return mContext.getString(R.string.notification_num_channels, numChannels);
+ private void waitForStopButton() {
+ PollingCheck.waitFor(1000,
+ () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
}
@Test
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.pkgname);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -170,24 +152,19 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final ImageView iconView = (ImageView) mNotificationInfo.findViewById(R.id.pkgicon);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@Test
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
- assertEquals(View.GONE, groupNameView.getVisibility());
- final TextView groupDividerView =
- (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider);
- assertEquals(View.GONE, groupDividerView.getVisibility());
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
+ assertEquals(GONE, groupNameView.getVisibility());
+ final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
+ assertEquals(GONE, groupDividerView.getVisibility());
}
@Test
@@ -199,75 +176,50 @@
eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
- final TextView groupDividerView =
- (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider);
+ final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
assertEquals(View.VISIBLE, groupDividerView.getVisibility());
}
@Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@Test
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
- assertEquals(mContext.getString(R.string.notification_header_default_channel),
- textView.getText());
+ TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+ assertEquals(GONE, textView.getVisibility());
}
@Test
- public void testBindNotification_UnblockablePackageDoesNotUseChannelName() throws Exception {
+ public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, Collections.singleton(TEST_PACKAGE_NAME));
- final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
- assertEquals(mContext.getString(R.string.notification_header_default_channel),
- textView.getText());
- }
-
- @Test
- public void testBindNotification_DefaultChannelUsesNameWhenMoreThanOneChannelExists()
- throws Exception {
- when(mMockINotificationManager.getNumNotificationChannelsForPackage(
- eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
- assertEquals(mDefaultNotificationChannel.getName(), textView.getText());
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+ final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+ assertEquals(VISIBLE, textView.getVisibility());
}
@Test
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, null, null, null);
+ }, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
// Verify that listener was triggered.
assertEquals(0, latch.getCount());
@@ -276,24 +228,20 @@
@Test
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
+ final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@Test
- public void testBindNotification_SettingsButtonReappersAfterSecondBind() throws Exception {
+ public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
- (View v, NotificationChannel c, int appUid) -> {}, null, null, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+ (View v, NotificationChannel c, int appUid) -> {
+ }, null, null);
+ final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -301,279 +249,63 @@
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME,
- Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
+ TEST_PACKAGE_NAME, mNotificationChannel, 2, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, null, null, null);
+ }, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
- settingsButton.performClick();
+ mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
assertEquals(0, latch.getCount());
}
@Test
- public void testBindNotification_SettingsTextWithOneChannel() throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
- (View v, NotificationChannel c, int appUid) -> {
- }, null, null, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
- assertEquals(getStringById(R.string.notification_more_settings), settingsButton.getText());
- }
-
- @Test
- public void testBindNotification_SettingsTextWithMultipleChannels() throws Exception {
- when(mMockINotificationManager.getNumNotificationChannelsForPackage(
- eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
- (View v, NotificationChannel c, int appUid) -> {
- }, null, null, null, null);
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
- assertEquals(getStringById(R.string.notification_all_categories), settingsButton.getText());
- }
-
- @Test
- public void testBindNotification_SettingsTextWithMultipleChannelsForUnblockableApp()
- throws Exception {
- when(mMockINotificationManager.getNumNotificationChannelsForPackage(
- eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn,
- (View v, NotificationChannel c, int appUid) -> {
- }, null, null, null, Collections.singleton(TEST_PACKAGE_NAME));
- final TextView settingsButton =
- (TextView) mNotificationInfo.findViewById(R.id.more_settings);
- assertEquals(getStringById(R.string.notification_more_settings), settingsButton.getText());
- }
-
- @Test
- public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null,
- null, (View v) -> {
- latch.countDown();
- },
- null, null);
-
- final TextView doneButton = (TextView) mNotificationInfo.findViewById(R.id.done);
- doneButton.performClick();
- // Verify that listener was triggered.
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null,
- null, null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(View.INVISIBLE, numChannelsView.getVisibility());
- }
-
- @Test
- public void testBindNotification_NumChannelsTextDisplaysWhenMoreThanOneChannelExists()
- throws Exception {
- when(mMockINotificationManager.getNumNotificationChannelsForPackage(
- eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null,
- null, null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(numChannelsView.getVisibility(), View.VISIBLE);
- assertEquals(getNumChannelsDescString(2), numChannelsView.getText());
- }
-
- @Test
- public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel()
- throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(numChannelsView.getVisibility(), View.VISIBLE);
- assertEquals(getNumChannelsDescString(1), numChannelsView.getText());
- }
-
- @Test
- public void testBindNotification_NumChannelsTextScalesWithNumberOfChannels()
- throws Exception {
- when(mMockINotificationManager.getNumNotificationChannelsForPackage(
- eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(getNumChannelsDescString(2), numChannelsView.getText());
- }
-
- @Test
@UiThreadTest
- public void testBindNotification_NumChannelsTextListsChannelsWhenTwoInBundle()
+ public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel),
- numChannelsView.getText());
- }
-
- @Test
- @UiThreadTest
- public void testBindNotification_NumChannelsTextListsChannelsWhenThreeInBundle()
- throws Exception {
- NotificationChannel thirdChannel = new NotificationChannel(
- "third_channel", "third_channel", NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME,
- Arrays.asList(mNotificationChannel, mDefaultNotificationChannel, thirdChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(
- getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel,
- thirdChannel),
- numChannelsView.getText());
- }
-
- @Test
- @UiThreadTest
- public void testBindNotification_NumChannelsTextListsChannelsWhenFourInBundle()
- throws Exception {
- NotificationChannel thirdChannel = new NotificationChannel(
- "third_channel", "third_channel", NotificationManager.IMPORTANCE_LOW);
- NotificationChannel fourthChannel = new NotificationChannel(
- "fourth_channel", "fourth_channel", NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME,
- Arrays.asList(mNotificationChannel, mDefaultNotificationChannel, thirdChannel,
- fourthChannel), mNotificationChannel.getImportance(), mSbn, null, null,
- null, null, null);
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(
- getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel,
- thirdChannel, fourthChannel),
- numChannelsView.getText());
- }
-
- @Test
- @UiThreadTest
- public void testBindNotification_ChannelNameChangesWhenBundleFromDifferentChannels()
- throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 2, mSbn, null, null, null, null);
final TextView channelNameView =
- (TextView) mNotificationInfo.findViewById(R.id.channel_name);
- assertEquals(getNumChannelsString(2), channelNameView.getText());
+ mNotificationInfo.findViewById(R.id.channel_name);
+ assertEquals(GONE, channelNameView.getVisibility());
}
@Test
@UiThreadTest
- public void testEnabledSwitchInvisibleIfBundleFromDifferentChannels() throws Exception {
+ public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
- public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null, null, null);
- final TextView channelDisabledView =
- (TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
- assertEquals(channelDisabledView.getVisibility(), View.GONE);
- }
-
- @Test
- public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
- final TextView channelDisabledView =
- (TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
- assertEquals(channelDisabledView.getVisibility(), View.VISIBLE);
- // Replaces the numChannelsView
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(numChannelsView.getVisibility(), View.GONE);
+ TEST_PACKAGE_NAME, mNotificationChannel, 2, mSbn, null, null, null, null);
+ final TextView blockView = mNotificationInfo.findViewById(R.id.block);
+ assertEquals(GONE, blockView.getVisibility());
}
@Test
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null,
null, Collections.singleton(TEST_PACKAGE_NAME));
- final TextView numChannelsView =
- (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(View.VISIBLE, numChannelsView.getVisibility());
+ final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
+ assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
- numChannelsView.getText());
- }
-
- @Test
- @UiThreadTest
- public void testBindNotification_ChannelDisabledTextShowsForDefaultChannel()
- throws Exception {
- mDefaultNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel),
- mDefaultNotificationChannel.getImportance(), mSbn, null, null,
- null, null, null);
- final TextView channelDisabledView =
- (TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
- assertEquals(View.VISIBLE, channelDisabledView.getVisibility());
+ view.getText());
}
@Test
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
}
@Test
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
+ mNotificationInfo.findViewById(R.id.block).performClick();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
}
@@ -582,9 +314,7 @@
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
mNotificationInfo.handleCloseControls(true, false);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -596,9 +326,7 @@
throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
mNotificationInfo.handleCloseControls(true, false);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -606,114 +334,25 @@
}
@Test
- public void testEnabledSwitchOnByDefault() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertTrue(enabledSwitch.isChecked());
- }
-
- @Test
- public void testEnabledButtonOffWhenAlreadyBanned() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertFalse(enabledSwitch.isChecked());
- }
-
- @Test
- public void testEnabledSwitchVisibleByDefault() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.VISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
- public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, Collections.singleton(TEST_PACKAGE_NAME));
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
- public void testEnabledSwitchInvisibleIfNonBlockableSystemChannel() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationChannel.setBlockableSystem(false);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
- public void testEnabledSwitchVisibleIfBlockableSystemChannel() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationChannel.setBlockableSystem(true);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, null);
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.VISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
- public void testEnabledSwitchInvisibleIfMultiChannelSummary() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- mNotificationChannel.setBlockableSystem(true);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, Collections.singleton(TEST_PACKAGE_NAME));
-
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
- }
-
- @Test
public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null,
null, Collections.singleton(TEST_PACKAGE_NAME));
- mNotificationInfo.handleCloseControls(true, false);
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
}
@Test
- public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, Collections.singleton(TEST_PACKAGE_NAME));
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);
- Switch enabledSwitch = mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
ArgumentCaptor<NotificationChannel> updated =
@@ -725,15 +364,35 @@
}
@Test
- public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ public void testBlockUndoDoesNotCallUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
- null, Collections.singleton(TEST_PACKAGE_NAME));
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
+ mNotificationInfo.findViewById(R.id.undo).performClick();
+ waitForStopButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+ }
+
+ @Test
+ public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
mNotificationInfo.handleCloseControls(false, false);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
@@ -741,16 +400,14 @@
@Test
public void testCloseControlsDoesNotUpdateIfCheckSaveListenerIsNoOp() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- },
- Collections.singleton(TEST_PACKAGE_NAME));
+ }, null, null, Collections.singleton(TEST_PACKAGE_NAME));
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
@@ -758,17 +415,15 @@
@Test
public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), mSbn, null, null, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- },
- Collections.singleton(TEST_PACKAGE_NAME));
+ }, null, null, null);
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
@@ -785,22 +440,19 @@
List<ResolveInfo> ris = new ArrayList<>();
ris.add(ri);
when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
.setSettingsText(settingsText).build();
StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), sbn, null,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, null, null, null);
+ }, null);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
- assertTrue(settingsLink.getText().toString().length() > settingsText.length());
- assertTrue(settingsLink.getText().toString().contains(settingsText));
settingsLink.performClick();
assertEquals(0, latch.getCount());
}
@@ -816,17 +468,17 @@
List<ResolveInfo> ris = new ArrayList<>();
ris.add(ri);
when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
.setSettingsText(settingsText).build();
StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
- mNotificationChannel.getImportance(), sbn, null, (View v, Intent intent) -> {
+ TEST_PACKAGE_NAME, mNotificationChannel, 2, sbn, null, null,
+ (View v, Intent intent) -> {
latch.countDown();
- }, null, null, null);
+ }, null);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -837,18 +489,16 @@
public void testNoSettingsLink_noHandlingActivity() throws Exception {
final String settingsText = "work chats";
when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(null);
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
.setSettingsText(settingsText).build();
StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), sbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 2, sbn, null, null, null, null);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(View.GONE, settingsLink.getVisibility());
+ assertEquals(GONE, settingsLink.getVisibility());
}
@Test
@@ -860,52 +510,17 @@
List<ResolveInfo> ris = new ArrayList<>();
ris.add(ri);
when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
Notification n = new Notification.Builder(mContext, mNotificationChannel.getId()).build();
StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), sbn, null, null, null,
- null, null);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, null);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(View.GONE, settingsLink.getVisibility());
+ assertEquals(GONE, settingsLink.getVisibility());
}
- @Test
- public void testNoSettingsLink_afterBlockingChannel() throws Exception {
- final String settingsText = "work chats";
- final ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = new ActivityInfo();
- ri.activityInfo.packageName = TEST_PACKAGE_NAME;
- ri.activityInfo.name = "something";
- List<ResolveInfo> ris = new ArrayList<>();
- ris.add(ri);
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
- .setSettingsText(settingsText).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
- mNotificationChannel.getImportance(), sbn, null, null, null,
- null, null);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(View.VISIBLE, settingsLink.getVisibility());
-
- // Block channel
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
- enabledSwitch.setChecked(false);
-
- assertEquals(View.GONE, settingsLink.getVisibility());
-
- //unblock
- enabledSwitch.setChecked(true);
- assertEquals(View.VISIBLE, settingsLink.getVisibility());
- }
@Test
public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 4c18f8d..30c7b53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -145,11 +145,10 @@
NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class);
Mockito.when(networkInfo.isConnected()).thenReturn(connected);
- WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
- Mockito.when(wifiInfo.getSSID()).thenReturn(ssid);
+ //TODO(b/69974497) mock of mWifiManager.getConnectionInfo() needed
+ // Mockito.when(wifiInfo.getSSID()).thenReturn(ssid);
i.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
- i.putExtra(WifiManager.EXTRA_WIFI_INFO, wifiInfo);
mNetworkController.onReceive(mContext, i);
}
@@ -176,7 +175,8 @@
assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
assertEquals("WiFi signal, in quick settings", icon, iconState.icon);
- assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
+ // TODO(b/69974497) Need to mock mWifiManager.getConnectionInfo() to supply the ssid.
+ // assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
}
protected void verifyLastWifiIcon(boolean visible, int icon) {
diff --git a/packages/VpnDialogs/res/values-pl/strings.xml b/packages/VpnDialogs/res/values-pl/strings.xml
index be6a4c2..d5201d7 100644
--- a/packages/VpnDialogs/res/values-pl/strings.xml
+++ b/packages/VpnDialogs/res/values-pl/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Żądanie połączenia"</string>
- <string name="warning" msgid="809658604548412033">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu sieciowego. Zaakceptuj, tylko jeśli masz zaufanie do źródła. Gdy sieć VPN jest aktywna, u góry ekranu pojawia się <br /> <br /> <img src=vpn_icon />."</string>
+ <string name="warning" msgid="809658604548412033">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu sieciowego. Zaakceptuj, tylko jeśli masz zaufanie do źródła. <br /> <br />Gdy sieć VPN jest aktywna, u góry ekranu pojawia się <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"Połączono z VPN"</string>
<string name="session" msgid="6470628549473641030">"Sesja:"</string>
<string name="duration" msgid="3584782459928719435">"Czas trwania:"</string>
diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml
index b9207a0..35ae7f7 100644
--- a/packages/VpnDialogs/res/values-ru/strings.xml
+++ b/packages/VpnDialogs/res/values-ru/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Запрос на подключение"</string>
- <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику.<br/><br/>Когда подключение VPN активно, в верхней части экрана появляется значок <img src=vpn_icon />."</string>
+ <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. <br /> <br />Когда подключение VPN активно, в верхней части экрана появляется значок <img src=vpn_icon />."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN-подключение установлено"</string>
<string name="session" msgid="6470628549473641030">"Сеанс:"</string>
<string name="duration" msgid="3584782459928719435">"Продолжительность:"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
index 2815312..0bd62ce 100644
--- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"网络连接请求"</string>
- <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>想要设置一个VPN连接(可被用于监控网络流量)。请只在您信任该来源的情况下才接受此请求。在VPN处于活动状态时,您的屏幕顶部会显示 <img src=vpn_icon /> 图标。"</string>
+ <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>想要设置一个 VPN 连接,以允许其监控网络流量。除非您信任该来源,否则请勿接受此请求。启用 VPN 时,您的屏幕顶部会显示 <img src=vpn_icon /> 图标。"</string>
<string name="legacy_title" msgid="192936250066580964">"已连接VPN"</string>
<string name="session" msgid="6470628549473641030">"会话:"</string>
<string name="duration" msgid="3584782459928719435">"时长:"</string>
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 1aaa538..4f04d36 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5124,6 +5124,11 @@
// OS: P
ACTION_USB_CONFIG_ACCESSORY = 1280;
+ // OPEN: Settings > Battery > Smart Battery
+ // CATEGORY: SETTINGS
+ // OS: P
+ FUELGAUGE_SMART_BATTERY = 1281;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 54cf726..85b0220 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -120,7 +120,6 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@@ -134,6 +133,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@@ -1568,6 +1568,57 @@
}
@Override
+ public void updateAppWidgetProviderInfo(ComponentName componentName, String metadataKey) {
+ final int userId = UserHandle.getCallingUserId();
+ if (DEBUG) {
+ Slog.i(TAG, "updateAppWidgetProvider() " + userId);
+ }
+
+ // Make sure the package runs under the caller uid.
+ mSecurityPolicy.enforceCallFromPackage(componentName.getPackageName());
+
+ synchronized (mLock) {
+ ensureGroupStateLoadedLocked(userId);
+
+ // NOTE: The lookup is enforcing security across users by making
+ // sure the caller can access only its providers.
+ ProviderId providerId = new ProviderId(Binder.getCallingUid(), componentName);
+ Provider provider = lookupProviderLocked(providerId);
+ if (provider == null) {
+ throw new IllegalArgumentException(
+ componentName + " is not a valid AppWidget provider");
+ }
+ if (Objects.equals(provider.infoTag, metadataKey)) {
+ // No change
+ return;
+ }
+
+ String keyToUse = metadataKey == null
+ ? AppWidgetManager.META_DATA_APPWIDGET_PROVIDER : metadataKey;
+ AppWidgetProviderInfo info =
+ parseAppWidgetProviderInfo(providerId, provider.info.providerInfo, keyToUse);
+ if (info == null) {
+ throw new IllegalArgumentException("Unable to parse " + keyToUse
+ + " meta-data to a valid AppWidget provider");
+ }
+
+ provider.info = info;
+ provider.infoTag = metadataKey;
+
+ // Update all widgets for this provider
+ final int N = provider.widgets.size();
+ for (int i = 0; i < N; i++) {
+ Widget widget = provider.widgets.get(i);
+ scheduleNotifyProviderChangedLocked(widget);
+ updateAppWidgetInstanceLocked(widget, widget.views, false /* isPartialUpdate */);
+ }
+
+ saveGroupStateAsync(userId);
+ scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
+ }
+ }
+
+ @Override
public boolean isRequestPinAppWidgetSupported() {
return LocalServices.getService(ShortcutServiceInternal.class)
.isRequestPinItemSupported(UserHandle.getCallingUserId(),
@@ -2168,7 +2219,7 @@
ri.activityInfo.name);
ProviderId providerId = new ProviderId(ri.activityInfo.applicationInfo.uid, componentName);
- Provider provider = parseProviderInfoXml(providerId, ri);
+ Provider provider = parseProviderInfoXml(providerId, ri, null);
if (provider != null) {
// we might have an inactive entry for this provider already due to
// a preceding restore operation. if so, fix it up in place; otherwise
@@ -2362,6 +2413,9 @@
out.attribute(null, "pkg", p.info.provider.getPackageName());
out.attribute(null, "cl", p.info.provider.getClassName());
out.attribute(null, "tag", Integer.toHexString(p.tag));
+ if (!TextUtils.isEmpty(p.infoTag)) {
+ out.attribute(null, "info_tag", p.infoTag);
+ }
out.endTag(null, "p");
}
@@ -2422,17 +2476,33 @@
}
@SuppressWarnings("deprecation")
- private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri) {
- Provider provider = null;
-
- ActivityInfo activityInfo = ri.activityInfo;
- XmlResourceParser parser = null;
- try {
- parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
+ private Provider parseProviderInfoXml(ProviderId providerId, ResolveInfo ri,
+ Provider oldProvider) {
+ AppWidgetProviderInfo info = null;
+ if (oldProvider != null && !TextUtils.isEmpty(oldProvider.infoTag)) {
+ info = parseAppWidgetProviderInfo(providerId, ri.activityInfo, oldProvider.infoTag);
+ }
+ if (info == null) {
+ info = parseAppWidgetProviderInfo(providerId, ri.activityInfo,
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
+ }
+ if (info == null) {
+ return null;
+ }
+
+ Provider provider = new Provider();
+ provider.id = providerId;
+ provider.info = info;
+ return provider;
+ }
+
+ private AppWidgetProviderInfo parseAppWidgetProviderInfo(
+ ProviderId providerId, ActivityInfo activityInfo, String metadataKey) {
+ try (XmlResourceParser parser =
+ activityInfo.loadXmlMetaData(mContext.getPackageManager(), metadataKey)) {
if (parser == null) {
- Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
- + " meta-data for " + "AppWidget provider '" + providerId + '\'');
+ Slog.w(TAG, "No " + metadataKey + " meta-data for AppWidget provider '"
+ + providerId + '\'');
return null;
}
@@ -2452,9 +2522,7 @@
return null;
}
- provider = new Provider();
- provider.id = providerId;
- AppWidgetProviderInfo info = provider.info = new AppWidgetProviderInfo();
+ AppWidgetProviderInfo info = new AppWidgetProviderInfo();
info.provider = providerId.componentName;
info.providerInfo = activityInfo;
@@ -2501,7 +2569,7 @@
className);
}
info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
- info.icon = ri.getIconResource();
+ info.icon = activityInfo.getIconResource();
info.previewImage = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
info.autoAdvanceViewId = sa.getResourceId(
@@ -2516,6 +2584,7 @@
com.android.internal.R.styleable.AppWidgetProviderInfo_widgetFeatures, 0);
sa.recycle();
+ return info;
} catch (IOException | PackageManager.NameNotFoundException | XmlPullParserException e) {
// Ok to catch Exception here, because anything going wrong because
// of what a client process passes to us should not be fatal for the
@@ -2523,12 +2592,7 @@
Slog.w(TAG, "XML parsing failed for AppWidget provider "
+ providerId.componentName + " for user " + providerId.uid, e);
return null;
- } finally {
- if (parser != null) {
- parser.close();
- }
}
- return provider;
}
private int getUidForPackage(String packageName, int userId) {
@@ -2891,7 +2955,7 @@
if (provider.getUserId() != userId) {
continue;
}
- if (provider.widgets.size() > 0) {
+ if (provider.shouldBePersisted()) {
serializeProvider(out, provider);
}
}
@@ -3000,6 +3064,15 @@
final int providerTag = !TextUtils.isEmpty(tagAttribute)
? Integer.parseInt(tagAttribute, 16) : legacyProviderIndex;
provider.tag = providerTag;
+
+ provider.infoTag = parser.getAttributeValue(null, "info_tag");
+ if (!TextUtils.isEmpty(provider.infoTag) && !mSafeMode) {
+ AppWidgetProviderInfo info = parseAppWidgetProviderInfo(
+ providerId, providerInfo, provider.infoTag);
+ if (info != null) {
+ provider.info = info;
+ }
+ }
} else if ("h".equals(tag)) {
legacyHostIndex++;
Host host = new Host();
@@ -3254,7 +3327,7 @@
providersUpdated = true;
}
} else {
- Provider parsed = parseProviderInfoXml(providerId, ri);
+ Provider parsed = parseProviderInfoXml(providerId, ri, provider);
if (parsed != null) {
keep.add(providerId);
// Use the new AppWidgetProviderInfo.
@@ -3725,6 +3798,7 @@
AppWidgetProviderInfo info;
ArrayList<Widget> widgets = new ArrayList<>();
PendingIntent broadcast;
+ String infoTag;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
boolean maskedByLockedProfile;
@@ -3784,6 +3858,10 @@
public boolean isMaskedLocked() {
return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
}
+
+ public boolean shouldBePersisted() {
+ return !widgets.isEmpty() || !TextUtils.isEmpty(infoTag);
+ }
}
private static final class ProviderId {
@@ -4114,7 +4192,7 @@
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
- if (!provider.widgets.isEmpty()
+ if (provider.shouldBePersisted()
&& (provider.isInPackageForUser(backedupPackage, userId)
|| provider.hostedByPackageForUser(backedupPackage, userId))) {
provider.tag = index;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 65984dd..da74dba 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -43,14 +43,19 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.Parcelable.Creator;
+import android.os.RemoteCallback;
import android.provider.Settings;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.Dataset;
import android.service.autofill.EditDistanceScorer;
import android.service.autofill.FieldClassification;
import android.service.autofill.FieldClassification.Match;
@@ -123,6 +128,8 @@
// TODO(b/70939974): temporary, will be moved to ExtServices
static final class FieldClassificationAlgorithmService {
+ static final String EXTRA_SCORES = "scores";
+
/**
* Gets the name of all available algorithms.
*/
@@ -140,28 +147,112 @@
}
/**
- * Gets a field classification score.
+ * Gets the field classification scores.
*
* @param algorithmName algorithm to be used. If invalid, the default algorithm will be used
* instead.
* @param algorithmArgs optional arguments to be passed to the algorithm.
- * @param actualValue value entered by the user.
- * @param userDataValue value from the user data.
- *
- * @return pair containing the algorithm used and the score.
+ * @param currentValues values entered by the user.
+ * @param userValues values from the user data.
+ * @param callback returns a nullable bundle with the parcelable results on
+ * {@link #EXTRA_SCORES}.
*/
- // TODO(b/70939974): use parcelable instead of pair
- Pair<String, Float> getScore(@NonNull String algorithmName, @Nullable Bundle algorithmArgs,
- @NonNull AutofillValue actualValue, @NonNull String userDataValue) {
- if (!EditDistanceScorer.NAME.equals(algorithmName)) {
- Log.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
- + EditDistanceScorer.NAME + " instead");
+ @Nullable
+ void getScores(@NonNull String algorithmName, @Nullable Bundle algorithmArgs,
+ List<AutofillValue> currentValues, @NonNull String[] userValues,
+ @NonNull RemoteCallback callback) {
+ if (currentValues == null || userValues == null) {
+ // TODO(b/70939974): use preconditions / add unit test
+ throw new IllegalArgumentException("values cannot be null");
}
- return new Pair<>(EditDistanceScorer.NAME,
- EditDistanceScorer.getInstance().getScore(actualValue, userDataValue));
+ if (currentValues.isEmpty() || userValues.length == 0) {
+ Slog.w(TAG, "getScores(): empty currentvalues (" + currentValues
+ + ") or userValues (" + Arrays.toString(userValues) + ")");
+ // TODO(b/70939974): add unit test
+ callback.sendResult(null);
+ }
+ String actualAlgorithName = algorithmName;
+ if (!EditDistanceScorer.NAME.equals(algorithmName)) {
+ Slog.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
+ + EditDistanceScorer.NAME + " instead");
+ actualAlgorithName = EditDistanceScorer.NAME;
+ }
+ final int currentValuesSize = currentValues.size();
+ if (sDebug) {
+ Log.d(TAG, "getScores() will return a " + currentValuesSize + "x"
+ + userValues.length + " matrix for " + actualAlgorithName);
+ }
+ final FieldClassificationScores scores = new FieldClassificationScores(
+ actualAlgorithName, currentValuesSize, userValues.length);
+ final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
+ for (int i = 0; i < currentValuesSize; i++) {
+ for (int j = 0; j < userValues.length; j++) {
+ final float score = algorithm.getScore(currentValues.get(i), userValues[j]);
+ scores.scores[i][j] = score;
+ }
+ }
+ final Bundle result = new Bundle();
+ result.putParcelable(EXTRA_SCORES, scores);
+ callback.sendResult(result);
}
}
+ // TODO(b/70939974): temporary, will be moved to ExtServices
+ public static final class FieldClassificationScores implements Parcelable {
+ public final String algorithmName;
+ public final float[][] scores;
+
+ public FieldClassificationScores(String algorithmName, int size1, int size2) {
+ this.algorithmName = algorithmName;
+ scores = new float[size1][size2];
+ }
+
+ public FieldClassificationScores(Parcel parcel) {
+ algorithmName = parcel.readString();
+ final int size1 = parcel.readInt();
+ final int size2 = parcel.readInt();
+ scores = new float[size1][size2];
+ for (int i = 0; i < size1; i++) {
+ for (int j = 0; j < size2; j++) {
+ scores[i][j] = parcel.readFloat();
+ }
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(algorithmName);
+ int size1 = scores.length;
+ int size2 = scores[0].length;
+ parcel.writeInt(size1);
+ parcel.writeInt(size2);
+ for (int i = 0; i < size1; i++) {
+ for (int j = 0; j < size2; j++) {
+ parcel.writeFloat(scores[i][j]);
+ }
+ }
+ }
+
+ public static final Creator<FieldClassificationScores> CREATOR = new Creator<FieldClassificationScores>() {
+
+ @Override
+ public FieldClassificationScores createFromParcel(Parcel parcel) {
+ return new FieldClassificationScores(parcel);
+ }
+
+ @Override
+ public FieldClassificationScores[] newArray(int size) {
+ return new FieldClassificationScores[size];
+ }
+
+ };
+ }
+
private final FieldClassificationAlgorithmService mFcService =
new FieldClassificationAlgorithmService();
@@ -776,10 +867,33 @@
@Nullable ArrayList<String> changedDatasetIds,
@Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
+ @NonNull String appPackageName) {
+ logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets,
+ changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
+ manuallyFilledDatasetIds, null, null, appPackageName);
+ }
+
+ void logContextCommittedLocked(int sessionId, @Nullable Bundle clientState,
+ @Nullable ArrayList<String> selectedDatasets,
+ @Nullable ArraySet<String> ignoredDatasets,
+ @Nullable ArrayList<AutofillId> changedFieldIds,
+ @Nullable ArrayList<String> changedDatasetIds,
+ @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
+ @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
@Nullable ArrayList<AutofillId> detectedFieldIdsList,
@Nullable ArrayList<FieldClassification> detectedFieldClassificationsList,
@NonNull String appPackageName) {
if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
+ if (sVerbose) {
+ Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId
+ + ", selectedDatasets=" + selectedDatasets
+ + ", ignoredDatasetIds=" + ignoredDatasets
+ + ", changedAutofillIds=" + changedFieldIds
+ + ", changedDatasetIds=" + changedDatasetIds
+ + ", manuallyFilledFieldIds=" + manuallyFilledFieldIds
+ + ", detectedFieldIds=" + detectedFieldIdsList
+ + ", detectedFieldClassifications=" + detectedFieldClassificationsList);
+ }
AutofillId[] detectedFieldsIds = null;
FieldClassification[] detectedFieldClassifications = null;
if (detectedFieldIdsList != null) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 9629690..f5d1336 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -25,11 +25,11 @@
import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
+import static com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService.EXTRA_SCORES;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sPartitionMaxCount;
import static com.android.server.autofill.Helper.sVerbose;
import static com.android.server.autofill.Helper.toArray;
-import static com.android.server.autofill.ViewState.STATE_AUTOFILLED;
import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
import android.annotation.NonNull;
@@ -51,11 +51,14 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcelable;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.AutofillService;
import android.service.autofill.Dataset;
+import android.service.autofill.FieldClassification;
import android.service.autofill.FieldClassification.Match;
+import android.service.carrier.CarrierMessagingService.ResultCallback;
import android.service.autofill.FillContext;
import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
@@ -65,11 +68,9 @@
import android.service.autofill.SaveRequest;
import android.service.autofill.UserData;
import android.service.autofill.ValueFinder;
-import android.service.autofill.FieldClassification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LocalLog;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -86,16 +87,19 @@
import com.android.internal.os.HandlerCaller;
import com.android.internal.util.ArrayUtils;
import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService;
+import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationScores;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.PendingUi;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
/**
* A session for a given activity.
@@ -972,18 +976,6 @@
final UserData userData = mService.getUserData();
- final ArrayList<AutofillId> detectedFieldIds;
- final ArrayList<FieldClassification> detectedFieldClassifications;
-
- if (userData != null) {
- final int maxFieldsSize = UserData.getMaxFieldClassificationIdsSize();
- detectedFieldIds = new ArrayList<>(maxFieldsSize);
- detectedFieldClassifications = new ArrayList<>(maxFieldsSize);
- } else {
- detectedFieldIds = null;
- detectedFieldClassifications = null;
- }
-
for (int i = 0; i < mViewStates.size(); i++) {
final ViewState viewState = mViewStates.valueAt(i);
final int state = viewState.getState();
@@ -1088,32 +1080,14 @@
} // for j
}
- // Sets field classification score for field
- if (userData!= null) {
- setFieldClassificationScore(mService.getFieldClassificationService(),
- detectedFieldIds, detectedFieldClassifications, userData,
- viewState.id, currentValue);
- }
} // else
} // else
}
- if (sVerbose) {
- Slog.v(TAG, "logContextCommitted(): id=" + id
- + ", selectedDatasetids=" + mSelectedDatasetIds
- + ", ignoredDatasetIds=" + ignoredDatasets
- + ", changedAutofillIds=" + changedFieldIds
- + ", changedDatasetIds=" + changedDatasetIds
- + ", manuallyFilledIds=" + manuallyFilledIds
- + ", detectedFieldIds=" + detectedFieldIds
- + ", detectedFieldClassifications=" + detectedFieldClassifications
- );
- }
-
ArrayList<AutofillId> manuallyFilledFieldIds = null;
ArrayList<ArrayList<String>> manuallyFilledDatasetIds = null;
- // Must "flatten" the map to the parcellable collection primitives
+ // Must "flatten" the map to the parcelable collection primitives
if (manuallyFilledIds != null) {
final int size = manuallyFilledIds.size();
manuallyFilledFieldIds = new ArrayList<>(size);
@@ -1126,22 +1100,35 @@
}
}
- mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds, ignoredDatasets,
- changedFieldIds, changedDatasetIds,
- manuallyFilledFieldIds, manuallyFilledDatasetIds,
- detectedFieldIds, detectedFieldClassifications, mComponentName.getPackageName());
+ // Sets field classification scores
+ final FieldClassificationAlgorithmService fcService =
+ mService.getFieldClassificationService();
+ if (userData != null && fcService != null) {
+ logFieldClassificationScoreLocked(fcService, ignoredDatasets, changedFieldIds,
+ changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds,
+ manuallyFilledIds, userData,
+ mViewStates.values());
+ } else {
+ mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
+ ignoredDatasets, changedFieldIds, changedDatasetIds,
+ manuallyFilledFieldIds, manuallyFilledDatasetIds,
+ mComponentName.getPackageName());
+ }
}
/**
* Adds the matches to {@code detectedFieldsIds} and {@code detectedFieldClassifications} for
* {@code fieldId} based on its {@code currentValue} and {@code userData}.
*/
- private static void setFieldClassificationScore(
- @NonNull AutofillManagerServiceImpl.FieldClassificationAlgorithmService service,
- @NonNull ArrayList<AutofillId> detectedFieldIds,
- @NonNull ArrayList<FieldClassification> detectedFieldClassifications,
- @NonNull UserData userData, @NonNull AutofillId fieldId,
- @NonNull AutofillValue currentValue) {
+ private void logFieldClassificationScoreLocked(
+ @NonNull AutofillManagerServiceImpl.FieldClassificationAlgorithmService fcService,
+ @NonNull ArraySet<String> ignoredDatasets,
+ @NonNull ArrayList<AutofillId> changedFieldIds,
+ @NonNull ArrayList<String> changedDatasetIds,
+ @NonNull ArrayList<AutofillId> manuallyFilledFieldIds,
+ @NonNull ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
+ @NonNull ArrayMap<AutofillId, ArraySet<String>> manuallyFilledIds,
+ @NonNull UserData userData, @NonNull Collection<ViewState> viewStates) {
final String[] userValues = userData.getValues();
final String[] remoteIds = userData.getRemoteIds();
@@ -1155,31 +1142,72 @@
return;
}
+ final int maxFieldsSize = UserData.getMaxFieldClassificationIdsSize();
+
+ final ArrayList<AutofillId> detectedFieldIds = new ArrayList<>(maxFieldsSize);
+ final ArrayList<FieldClassification> detectedFieldClassifications = new ArrayList<>(
+ maxFieldsSize);
+
final String algorithm = userData.getFieldClassificationAlgorithm();
final Bundle algorithmArgs = userData.getAlgorithmArgs();
- ArrayList<Match> matches = null;
- for (int i = 0; i < userValues.length; i++) {
- String remoteId = remoteIds[i];
- final String value = userValues[i];
- final Pair<String, Float> result = service.getScore(algorithm, algorithmArgs,
- currentValue, value);
- final String actualAlgorithm = result.first;
- final float score = result.second;
- if (score > 0) {
- if (sVerbose) {
- Slog.v(TAG, "adding score " + score + " at index " + i + " and id " + fieldId);
- }
- if (matches == null) {
- matches = new ArrayList<>(userValues.length);
- }
- matches.add(new Match(remoteId, score, actualAlgorithm));
+ final int viewsSize = viewStates.size();
+
+ // First, we get all scores.
+ final AutofillId[] fieldIds = new AutofillId[viewsSize];
+ final ArrayList<AutofillValue> currentValues = new ArrayList<>(viewsSize);
+ int k = 0;
+ for (ViewState viewState : viewStates) {
+ currentValues.add(viewState.getCurrentValue());
+ fieldIds[k++] = viewState.id;
+ }
+
+ final RemoteCallback callback = new RemoteCallback((result) -> {
+ if (result == null) {
+ if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
+ mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
+ ignoredDatasets, changedFieldIds, changedDatasetIds,
+ manuallyFilledFieldIds, manuallyFilledDatasetIds,
+ mComponentName.getPackageName());
+ return;
}
- else if (sVerbose) Slog.v(TAG, "skipping score 0 at index " + i + " and id " + fieldId);
- }
- if (matches != null) {
- detectedFieldIds.add(fieldId);
- detectedFieldClassifications.add(new FieldClassification(matches));
- }
+ final FieldClassificationScores matrix = result.getParcelable(EXTRA_SCORES);
+
+ // Then use the results.
+ for (int i = 0; i < viewsSize; i++) {
+ final AutofillId fieldId = fieldIds[i];
+
+ ArrayList<Match> matches = null;
+ for (int j = 0; j < userValues.length; j++) {
+ String remoteId = remoteIds[j];
+ final String actualAlgorithm = matrix.algorithmName;
+ final float score = matrix.scores[i][j];
+ if (score > 0) {
+ if (sVerbose) {
+ Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
+ + fieldId);
+ }
+ if (matches == null) {
+ matches = new ArrayList<>(userValues.length);
+ }
+ matches.add(new Match(remoteId, score, actualAlgorithm));
+ }
+ else if (sVerbose) {
+ Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
+ }
+ }
+ if (matches != null) {
+ detectedFieldIds.add(fieldId);
+ detectedFieldClassifications.add(new FieldClassification(matches));
+ }
+ }
+
+ mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
+ ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
+ manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications,
+ mComponentName.getPackageName());
+ });
+
+ fcService.getScores(algorithm, algorithmArgs, currentValues, userValues, callback);
}
/**
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index b17f794..1a54e95 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -85,9 +85,6 @@
super(handler);
mResolver = resolver;
updateSettings();
- }
-
- public void start() {
mResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS), false, this);
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
index 86462d8..7b021c6 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
@@ -186,6 +186,8 @@
boolean isAppEligibleForBackup(String packageName);
+ String[] filterAppsEligibleForBackup(String[] packages);
+
void dump(FileDescriptor fd, PrintWriter pw, String[] args);
IBackupManager getBackupManagerBinder();
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 2d2993d..3cf374f 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -70,12 +70,28 @@
private static final String DEFAULT_HOME_KEY = "@home@";
// Sentinel: start of state file, followed by a version number
+ // Note that STATE_FILE_VERSION=2 is tied to UNDEFINED_ANCESTRAL_RECORD_VERSION=-1 *as well as*
+ // ANCESTRAL_RECORD_VERSION=1 (introduced Android P).
+ // Should the ANCESTRAL_RECORD_VERSION be bumped up in the future, STATE_FILE_VERSION will also
+ // need bumping up, assuming more data needs saving to the state file.
private static final String STATE_FILE_HEADER = "=state=";
private static final int STATE_FILE_VERSION = 2;
- // Current version of the saved ancestral-dataset file format
+ // key under which we store the saved ancestral-dataset format (starting from Android P)
+ // IMPORTANT: this key needs to come first in the restore data stream (to find out
+ // whether this version of Android knows how to restore the incoming data set), so it needs
+ // to be always the first one in alphabetical order of all the keys
+ private static final String ANCESTRAL_RECORD_KEY = "@ancestral_record@";
+
+ // Current version of the saved ancestral-dataset format
+ // Note that this constant was not used until Android P, and started being used
+ // to version @pm@ data for forwards-compatibility.
private static final int ANCESTRAL_RECORD_VERSION = 1;
+ // Undefined version of the saved ancestral-dataset file format means that the restore data
+ // is coming from pre-Android P device.
+ private static final int UNDEFINED_ANCESTRAL_RECORD_VERSION = -1;
+
private List<PackageInfo> mAllPackages;
private PackageManager mPackageManager;
// version & signature info of each app in a restore set
@@ -175,9 +191,8 @@
// additional involvement by the transport to obtain.
return mRestoredSignatures.keySet();
}
-
- // The backed up data is the signature block for each app, keyed by
- // the package name.
+
+ // The backed up data is the signature block for each app, keyed by the package name.
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
if (DEBUG) Slog.v(TAG, "onBackup()");
@@ -196,6 +211,22 @@
mExisting.clear();
}
+ /*
+ * Ancestral record version:
+ *
+ * int ancestralRecordVersion -- the version of the format in which this backup set is
+ * produced
+ */
+ try {
+ if (DEBUG) Slog.v(TAG, "Storing ancestral record version key");
+ outputBufferStream.writeInt(ANCESTRAL_RECORD_VERSION);
+ writeEntity(data, ANCESTRAL_RECORD_KEY, outputBuffer.toByteArray());
+ } catch (IOException e) {
+ // Real error writing data
+ Slog.e(TAG, "Unable to write package backup data file!");
+ return;
+ }
+
long homeVersion = 0;
ArrayList<byte[]> homeSigHashes = null;
PackageInfo homeInfo = null;
@@ -230,6 +261,7 @@
Slog.i(TAG, "Home preference changed; backing up new state " + home);
}
if (home != null) {
+ outputBuffer.reset();
outputBufferStream.writeUTF(home.flattenToString());
outputBufferStream.writeLong(homeVersion);
outputBufferStream.writeUTF(homeInstaller != null ? homeInstaller : "" );
@@ -244,8 +276,8 @@
* Global metadata:
*
* int SDKversion -- the SDK version of the OS itself on the device
- * that produced this backup set. Used to reject
- * backups from later OSes onto earlier ones.
+ * that produced this backup set. Before Android P it was used to
+ * reject backups from later OSes onto earlier ones.
* String incremental -- the incremental release name of the OS stored in
* the backup set.
*/
@@ -354,7 +386,7 @@
// Finally, write the new state blob -- just the list of all apps we handled
writeStateFile(mAllPackages, home, homeVersion, homeSigHashes, newState);
}
-
+
private static void writeEntity(BackupDataOutput data, String key, byte[] bytes)
throws IOException {
data.writeEntityHeader(key, bytes.length);
@@ -366,83 +398,57 @@
// image. We'll use those later to determine what we can legitimately restore.
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
- List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
- HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
if (DEBUG) Slog.v(TAG, "onRestore()");
- int storedSystemVersion = -1;
- while (data.readNextHeader()) {
+ // we expect the ANCESTRAL_RECORD_KEY ("@ancestral_record@") to always come first in the
+ // restore set - based on that value we use different mechanisms to consume the data;
+ // if the ANCESTRAL_RECORD_KEY is missing in the restore set, it means that the data is
+ // is coming from a pre-Android P device, and we consume the header data in the legacy way
+ // TODO: add a CTS test to verify that backups of PMBA generated on Android P+ always
+ // contain the ANCESTRAL_RECORD_KEY, and it's always the first key
+ int ancestralRecordVersion = getAncestralRecordVersionValue(data);
+
+ RestoreDataConsumer consumer = getRestoreDataConsumer(ancestralRecordVersion);
+ if (consumer == null) {
+ Slog.w(TAG, "Ancestral restore set version is unknown"
+ + " to this Android version; not restoring");
+ return;
+ } else {
+ consumer.consumeRestoreData(data);
+ }
+ }
+
+ private int getAncestralRecordVersionValue(BackupDataInput data) throws IOException {
+ int ancestralRecordVersionValue = UNDEFINED_ANCESTRAL_RECORD_VERSION;
+ if (data.readNextHeader()) {
String key = data.getKey();
int dataSize = data.getDataSize();
if (DEBUG) Slog.v(TAG, " got key=" + key + " dataSize=" + dataSize);
- // generic setup to parse any entity data
- byte[] inputBytes = new byte[dataSize];
- data.readEntityData(inputBytes, 0, dataSize);
- ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes);
- DataInputStream inputBufferStream = new DataInputStream(inputBuffer);
+ if (ANCESTRAL_RECORD_KEY.equals(key)) {
+ // generic setup to parse any entity data
+ byte[] inputBytes = new byte[dataSize];
+ data.readEntityData(inputBytes, 0, dataSize);
+ ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes);
+ DataInputStream inputBufferStream = new DataInputStream(inputBuffer);
- if (key.equals(GLOBAL_METADATA_KEY)) {
- int storedSdkVersion = inputBufferStream.readInt();
- if (DEBUG) Slog.v(TAG, " storedSystemVersion = " + storedSystemVersion);
- if (storedSystemVersion > Build.VERSION.SDK_INT) {
- // returning before setting the sig map means we rejected the restore set
- Slog.w(TAG, "Restore set was from a later version of Android; not restoring");
- return;
- }
- mStoredSdkVersion = storedSdkVersion;
- mStoredIncrementalVersion = inputBufferStream.readUTF();
- mHasMetadata = true;
- if (DEBUG) {
- Slog.i(TAG, "Restore set version " + storedSystemVersion
- + " is compatible with OS version " + Build.VERSION.SDK_INT
- + " (" + mStoredIncrementalVersion + " vs "
- + Build.VERSION.INCREMENTAL + ")");
- }
- } else if (key.equals(DEFAULT_HOME_KEY)) {
- String cn = inputBufferStream.readUTF();
- mRestoredHome = ComponentName.unflattenFromString(cn);
- mRestoredHomeVersion = inputBufferStream.readLong();
- mRestoredHomeInstaller = inputBufferStream.readUTF();
- mRestoredHomeSigHashes = readSignatureHashArray(inputBufferStream);
- if (DEBUG) {
- Slog.i(TAG, " read preferred home app " + mRestoredHome
- + " version=" + mRestoredHomeVersion
- + " installer=" + mRestoredHomeInstaller
- + " sig=" + mRestoredHomeSigHashes);
- }
- } else {
- // it's a file metadata record
- int versionCodeInt = inputBufferStream.readInt();
- long versionCode;
- if (versionCodeInt == Integer.MIN_VALUE) {
- versionCode = inputBufferStream.readLong();
- } else {
- versionCode = versionCodeInt;
- }
- ArrayList<byte[]> sigs = readSignatureHashArray(inputBufferStream);
- if (DEBUG) {
- Slog.i(TAG, " read metadata for " + key
- + " dataSize=" + dataSize
- + " versionCode=" + versionCode + " sigs=" + sigs);
- }
-
- if (sigs == null || sigs.size() == 0) {
- Slog.w(TAG, "Not restoring package " + key
- + " since it appears to have no signatures.");
- continue;
- }
-
- ApplicationInfo app = new ApplicationInfo();
- app.packageName = key;
- restoredApps.add(app);
- sigMap.put(key, new Metadata(versionCode, sigs));
+ ancestralRecordVersionValue = inputBufferStream.readInt();
}
}
+ return ancestralRecordVersionValue;
+ }
- // On successful completion, cache the signature map for the Backup Manager to use
- mRestoredSignatures = sigMap;
+ private RestoreDataConsumer getRestoreDataConsumer(int ancestralRecordVersion) {
+ switch (ancestralRecordVersion) {
+ case UNDEFINED_ANCESTRAL_RECORD_VERSION:
+ return new LegacyRestoreDataConsumer();
+ case 1:
+ return new AncestralVersion1RestoreDataConsumer();
+ default:
+ Slog.e(TAG, "Unrecognized ANCESTRAL_RECORD_VERSION: " + ancestralRecordVersion);
+ return null;
+ }
}
private static void writeSignatureHashArray(DataOutputStream out, ArrayList<byte[]> hashes)
@@ -639,4 +645,173 @@
Slog.e(TAG, "Unable to write package manager state file!");
}
}
+
+ interface RestoreDataConsumer {
+ void consumeRestoreData(BackupDataInput data) throws IOException;
+ }
+
+ private class LegacyRestoreDataConsumer implements RestoreDataConsumer {
+
+ public void consumeRestoreData(BackupDataInput data) throws IOException {
+ List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
+ HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
+ int storedSystemVersion = -1;
+
+ if (DEBUG) Slog.i(TAG, "Using LegacyRestoreDataConsumer");
+ // we already have the first header read and "cached", since ANCESTRAL_RECORD_KEY
+ // was missing
+ while (true) {
+ String key = data.getKey();
+ int dataSize = data.getDataSize();
+
+ if (DEBUG) Slog.v(TAG, " got key=" + key + " dataSize=" + dataSize);
+
+ // generic setup to parse any entity data
+ byte[] inputBytes = new byte[dataSize];
+ data.readEntityData(inputBytes, 0, dataSize);
+ ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes);
+ DataInputStream inputBufferStream = new DataInputStream(inputBuffer);
+
+ if (key.equals(GLOBAL_METADATA_KEY)) {
+ int storedSdkVersion = inputBufferStream.readInt();
+ if (DEBUG) Slog.v(TAG, " storedSystemVersion = " + storedSystemVersion);
+ mStoredSdkVersion = storedSdkVersion;
+ mStoredIncrementalVersion = inputBufferStream.readUTF();
+ mHasMetadata = true;
+ if (DEBUG) {
+ Slog.i(TAG, "Restore set version " + storedSystemVersion
+ + " is compatible with OS version " + Build.VERSION.SDK_INT
+ + " (" + mStoredIncrementalVersion + " vs "
+ + Build.VERSION.INCREMENTAL + ")");
+ }
+ } else if (key.equals(DEFAULT_HOME_KEY)) {
+ String cn = inputBufferStream.readUTF();
+ mRestoredHome = ComponentName.unflattenFromString(cn);
+ mRestoredHomeVersion = inputBufferStream.readLong();
+ mRestoredHomeInstaller = inputBufferStream.readUTF();
+ mRestoredHomeSigHashes = readSignatureHashArray(inputBufferStream);
+ if (DEBUG) {
+ Slog.i(TAG, " read preferred home app " + mRestoredHome
+ + " version=" + mRestoredHomeVersion
+ + " installer=" + mRestoredHomeInstaller
+ + " sig=" + mRestoredHomeSigHashes);
+ }
+ } else {
+ // it's a file metadata record
+ int versionCodeInt = inputBufferStream.readInt();
+ long versionCode;
+ if (versionCodeInt == Integer.MIN_VALUE) {
+ versionCode = inputBufferStream.readLong();
+ } else {
+ versionCode = versionCodeInt;
+ }
+ ArrayList<byte[]> sigs = readSignatureHashArray(inputBufferStream);
+ if (DEBUG) {
+ Slog.i(TAG, " read metadata for " + key
+ + " dataSize=" + dataSize
+ + " versionCode=" + versionCode + " sigs=" + sigs);
+ }
+
+ if (sigs == null || sigs.size() == 0) {
+ Slog.w(TAG, "Not restoring package " + key
+ + " since it appears to have no signatures.");
+ continue;
+ }
+
+ ApplicationInfo app = new ApplicationInfo();
+ app.packageName = key;
+ restoredApps.add(app);
+ sigMap.put(key, new Metadata(versionCode, sigs));
+ }
+
+ boolean readNextHeader = data.readNextHeader();
+ if (!readNextHeader) {
+ if (DEBUG) Slog.v(TAG, "LegacyRestoreDataConsumer:"
+ + " we're done reading all the headers");
+ break;
+ }
+ }
+
+ // On successful completion, cache the signature map for the Backup Manager to use
+ mRestoredSignatures = sigMap;
+ }
+ }
+
+ private class AncestralVersion1RestoreDataConsumer implements RestoreDataConsumer {
+
+ public void consumeRestoreData(BackupDataInput data) throws IOException {
+ List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
+ HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
+ int storedSystemVersion = -1;
+
+ if (DEBUG) Slog.i(TAG, "Using AncestralVersion1RestoreDataConsumer");
+ while (data.readNextHeader()) {
+ String key = data.getKey();
+ int dataSize = data.getDataSize();
+
+ if (DEBUG) Slog.v(TAG, " got key=" + key + " dataSize=" + dataSize);
+
+ // generic setup to parse any entity data
+ byte[] inputBytes = new byte[dataSize];
+ data.readEntityData(inputBytes, 0, dataSize);
+ ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes);
+ DataInputStream inputBufferStream = new DataInputStream(inputBuffer);
+
+ if (key.equals(GLOBAL_METADATA_KEY)) {
+ int storedSdkVersion = inputBufferStream.readInt();
+ if (DEBUG) Slog.v(TAG, " storedSystemVersion = " + storedSystemVersion);
+ mStoredSdkVersion = storedSdkVersion;
+ mStoredIncrementalVersion = inputBufferStream.readUTF();
+ mHasMetadata = true;
+ if (DEBUG) {
+ Slog.i(TAG, "Restore set version " + storedSystemVersion
+ + " is compatible with OS version " + Build.VERSION.SDK_INT
+ + " (" + mStoredIncrementalVersion + " vs "
+ + Build.VERSION.INCREMENTAL + ")");
+ }
+ } else if (key.equals(DEFAULT_HOME_KEY)) {
+ String cn = inputBufferStream.readUTF();
+ mRestoredHome = ComponentName.unflattenFromString(cn);
+ mRestoredHomeVersion = inputBufferStream.readLong();
+ mRestoredHomeInstaller = inputBufferStream.readUTF();
+ mRestoredHomeSigHashes = readSignatureHashArray(inputBufferStream);
+ if (DEBUG) {
+ Slog.i(TAG, " read preferred home app " + mRestoredHome
+ + " version=" + mRestoredHomeVersion
+ + " installer=" + mRestoredHomeInstaller
+ + " sig=" + mRestoredHomeSigHashes);
+ }
+ } else {
+ // it's a file metadata record
+ int versionCodeInt = inputBufferStream.readInt();
+ long versionCode;
+ if (versionCodeInt == Integer.MIN_VALUE) {
+ versionCode = inputBufferStream.readLong();
+ } else {
+ versionCode = versionCodeInt;
+ }
+ ArrayList<byte[]> sigs = readSignatureHashArray(inputBufferStream);
+ if (DEBUG) {
+ Slog.i(TAG, " read metadata for " + key
+ + " dataSize=" + dataSize
+ + " versionCode=" + versionCode + " sigs=" + sigs);
+ }
+
+ if (sigs == null || sigs.size() == 0) {
+ Slog.w(TAG, "Not restoring package " + key
+ + " since it appears to have no signatures.");
+ continue;
+ }
+
+ ApplicationInfo app = new ApplicationInfo();
+ app.packageName = key;
+ restoredApps.add(app);
+ sigMap.put(key, new Metadata(versionCode, sigs));
+ }
+ }
+
+ // On successful completion, cache the signature map for the Backup Manager to use
+ mRestoredSignatures = sigMap;
+ }
+ }
}
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 51c44e1..03591a8 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -148,6 +148,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
@@ -1605,9 +1606,15 @@
return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
}
- TransportClient transportClient =
- mTransportManager.getCurrentTransportClient("BMS.requestBackup()");
- if (transportClient == null) {
+ final TransportClient transportClient;
+ final String transportDirName;
+ try {
+ transportDirName =
+ mTransportManager.getTransportDirName(
+ mTransportManager.getCurrentTransportName());
+ transportClient =
+ mTransportManager.getCurrentTransportClientOrThrow("BMS.requestBackup()");
+ } catch (TransportNotRegisteredException e) {
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
@@ -1652,12 +1659,11 @@
+ " k/v backups");
}
- String dirName = transportClient.getTransportDirName();
boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;
Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
- msg.obj = new BackupParams(transportClient, dirName, kvBackupList, fullBackupList, observer,
- monitor, listener, true, nonIncrementalBackup);
+ msg.obj = new BackupParams(transportClient, transportDirName, kvBackupList, fullBackupList,
+ observer, monitor, listener, true, nonIncrementalBackup);
mBackupHandler.sendMessage(msg);
return BackupManager.SUCCESS;
}
@@ -2995,63 +3001,63 @@
}
}
- // Select which transport to use for the next backup operation.
+ /** Selects transport {@code transportName} and returns previous selected transport. */
@Override
- public String selectBackupTransport(String transport) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "selectBackupTransport");
+ public String selectBackupTransport(String transportName) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "selectBackupTransport");
final long oldId = Binder.clearCallingIdentity();
try {
- String prevTransport = mTransportManager.selectTransport(transport);
- updateStateForTransport(transport);
- Slog.v(TAG, "selectBackupTransport() set " + mTransportManager.getCurrentTransportName()
- + " returning " + prevTransport);
- return prevTransport;
+ String previousTransportName = mTransportManager.selectTransport(transportName);
+ updateStateForTransport(transportName);
+ Slog.v(TAG, "selectBackupTransport(transport = " + transportName
+ + "): previous transport = " + previousTransportName);
+ return previousTransportName;
} finally {
Binder.restoreCallingIdentity(oldId);
}
}
@Override
- public void selectBackupTransportAsync(final ComponentName transport,
- final ISelectBackupTransportCallback listener) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "selectBackupTransportAsync");
+ public void selectBackupTransportAsync(
+ ComponentName transportComponent, ISelectBackupTransportCallback listener) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "selectBackupTransportAsync");
final long oldId = Binder.clearCallingIdentity();
-
- Slog.v(TAG, "selectBackupTransportAsync() called with transport " +
- transport.flattenToShortString());
-
- mTransportManager.ensureTransportReady(transport,
- new TransportManager.TransportReadyCallback() {
- @Override
- public void onSuccess(String transportName) {
- mTransportManager.selectTransport(transportName);
- updateStateForTransport(mTransportManager.getCurrentTransportName());
- Slog.v(TAG, "Transport successfully selected: "
- + transport.flattenToShortString());
- try {
- listener.onSuccess(transportName);
- } catch (RemoteException e) {
- // Nothing to do here.
+ try {
+ String transportString = transportComponent.flattenToShortString();
+ Slog.v(TAG, "selectBackupTransportAsync(transport = " + transportString + ")");
+ mBackupHandler.post(
+ () -> {
+ String transportName = null;
+ int result =
+ mTransportManager.registerAndSelectTransport(transportComponent);
+ if (result == BackupManager.SUCCESS) {
+ try {
+ transportName =
+ mTransportManager.getTransportName(transportComponent);
+ updateStateForTransport(transportName);
+ } catch (TransportNotRegisteredException e) {
+ Slog.e(TAG, "Transport got unregistered");
+ result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
+ }
}
- }
- @Override
- public void onFailure(int reason) {
- Slog.v(TAG,
- "Failed to select transport: " + transport.flattenToShortString());
try {
- listener.onFailure(reason);
+ if (transportName != null) {
+ listener.onSuccess(transportName);
+ } else {
+ listener.onFailure(result);
+ }
} catch (RemoteException e) {
- // Nothing to do here.
+ Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
}
- }
- });
-
- Binder.restoreCallingIdentity(oldId);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
}
private void updateStateForTransport(String newTransportName) {
@@ -3060,18 +3066,23 @@
Settings.Secure.BACKUP_TRANSPORT, newTransportName);
// And update our current-dataset bookkeeping
- IBackupTransport transport = mTransportManager.getTransportBinder(newTransportName);
- if (transport != null) {
+ String callerLogString = "BMS.updateStateForTransport()";
+ TransportClient transportClient =
+ mTransportManager.getTransportClient(newTransportName, callerLogString);
+ if (transportClient != null) {
try {
+ IBackupTransport transport = transportClient.connectOrThrow(callerLogString);
mCurrentToken = transport.getCurrentRestoreSet();
} catch (Exception e) {
// Oops. We can't know the current dataset token, so reset and figure it out
// when we do the next k/v backup operation on this transport.
mCurrentToken = 0;
+ Slog.w(TAG, "Transport " + newTransportName + " not available: current token = 0");
}
} else {
- // The named transport isn't bound at this particular moment, so we can't
- // know yet what its current dataset token is. Reset as above.
+ Slog.w(TAG, "Transport " + newTransportName + " not registered: current token = 0");
+ // The named transport isn't registered, so we can't know what its current dataset token
+ // is. Reset as above.
mCurrentToken = 0;
}
}
@@ -3095,29 +3106,30 @@
}
}
- // Supply the configuration summary string for the given transport. If the name is
- // not one of the available transports, or if the transport does not supply any
- // summary / destination string, the method can return null.
- //
- // This string is used VERBATIM as the summary text of the relevant Settings item!
+ /**
+ * Supply the current destination string for the given transport. If the name is not one of the
+ * registered transports the method will return null.
+ *
+ * <p>This string is used VERBATIM as the summary text of the relevant Settings item.
+ *
+ * @param transportName The name of the registered transport.
+ * @return The current destination string or null if the transport is not registered.
+ */
@Override
public String getDestinationString(String transportName) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "getDestinationString");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "getDestinationString");
- final IBackupTransport transport = mTransportManager.getTransportBinder(transportName);
- if (transport != null) {
- try {
- final String text = transport.currentDestinationString();
- if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text);
- return text;
- } catch (Exception e) {
- /* fall through to return null */
- Slog.e(TAG, "Unable to get string from transport: " + e.getMessage());
+ try {
+ String string = mTransportManager.getTransportCurrentDestinationString(transportName);
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "getDestinationString() returning " + string);
}
+ return string;
+ } catch (TransportNotRegisteredException e) {
+ Slog.e(TAG, "Unable to get destination string from transport: " + e.getMessage());
+ return null;
}
-
- return null;
}
// Supply the manage-data intent for the given transport.
@@ -3387,31 +3399,41 @@
@Override
public boolean isAppEligibleForBackup(String packageName) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "isAppEligibleForBackup");
- try {
- PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
- PackageManager.GET_SIGNATURES);
- if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo,
- mPackageManager) ||
- AppBackupUtils.appIsStopped(packageInfo.applicationInfo) ||
- AppBackupUtils.appIsDisabled(packageInfo.applicationInfo, mPackageManager)) {
- return false;
- }
- IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
- if (transport != null) {
- try {
- return transport.isAppEligibleForBackup(packageInfo,
- AppBackupUtils.appGetsFullBackup(packageInfo));
- } catch (Exception e) {
- Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
- }
- }
- // If transport is not present we couldn't tell that the package is not eligible.
- return true;
- } catch (NameNotFoundException e) {
- return false;
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "isAppEligibleForBackup");
+
+ String callerLogString = "BMS.isAppEligibleForBackup";
+ TransportClient transportClient =
+ mTransportManager.getCurrentTransportClient(callerLogString);
+ boolean eligible =
+ AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
+ transportClient, packageName, mPackageManager);
+ if (transportClient != null) {
+ mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
}
+ return eligible;
+ }
+
+ @Override
+ public String[] filterAppsEligibleForBackup(String[] packages) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup");
+
+ String callerLogString = "BMS.filterAppsEligibleForBackup";
+ TransportClient transportClient =
+ mTransportManager.getCurrentTransportClient(callerLogString);
+ List<String> eligibleApps = new LinkedList<>();
+ for (String packageName : packages) {
+ if (AppBackupUtils
+ .appIsRunningAndEligibleForBackupWithTransport(
+ transportClient, packageName, mPackageManager)) {
+ eligibleApps.add(packageName);
+ }
+ }
+ if (transportClient != null) {
+ mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+ }
+ return eligibleApps.toArray(new String[eligibleApps.size()]);
}
@Override
@@ -3475,10 +3497,10 @@
pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? " * "
: " ") + t);
try {
- IBackupTransport transport = mTransportManager.getTransportBinder(t);
File dir = new File(mBaseStateDir,
mTransportManager.getTransportDirName(t));
- pw.println(" destination: " + transport.currentDestinationString());
+ pw.println(" destination: "
+ + mTransportManager.getTransportCurrentDestinationString(t));
pw.println(" intent: "
+ mTransportManager.getTransportConfigurationIntent(t));
for (File f : dir.listFiles()) {
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 94a26275..a628c9d 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -452,6 +452,12 @@
}
@Override
+ public String[] filterAppsEligibleForBackup(String[] packages) {
+ BackupManagerServiceInterface svc = mService;
+ return (svc != null) ? svc.filterAppsEligibleForBackup(packages) : null;
+ }
+
+ @Override
public int requestBackup(String[] packages, IBackupObserver observer,
IBackupManagerMonitor monitor, int flags) throws RemoteException {
BackupManagerServiceInterface svc = mService;
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index fbdb183..34b8935 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -49,6 +49,7 @@
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportClientManager;
import com.android.server.backup.transport.TransportConnectionListener;
+import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.transport.TransportNotRegisteredException;
import java.util.ArrayList;
@@ -111,23 +112,6 @@
@GuardedBy("mTransportLock")
private volatile String mCurrentTransportName;
-
- /**
- * Callback interface for {@link #ensureTransportReady(ComponentName, TransportReadyCallback)}.
- */
- public interface TransportReadyCallback {
-
- /**
- * Will be called when the transport is ready.
- */
- void onSuccess(String transportName);
-
- /**
- * Will be called when it's not possible to make transport ready.
- */
- void onFailure(int reason);
- }
-
TransportManager(
Context context,
Set<ComponentName> whitelist,
@@ -239,6 +223,17 @@
}
/**
+ * Returns the transport name associated with {@code transportComponent}.
+ * @throws TransportNotRegisteredException if the transport is not registered.
+ */
+ public String getTransportName(ComponentName transportComponent)
+ throws TransportNotRegisteredException {
+ synchronized (mTransportLock) {
+ return getRegisteredTransportDescriptionOrThrowLocked(transportComponent).name;
+ }
+ }
+
+ /**
* Retrieve the configuration intent of {@code transportName}.
* @throws TransportNotRegisteredException if the transport is not registered.
*/
@@ -265,6 +260,18 @@
}
/**
+ * Retrieve the current destination string of {@code transportName}.
+ * @throws TransportNotRegisteredException if the transport is not registered.
+ */
+ public String getTransportCurrentDestinationString(String transportName)
+ throws TransportNotRegisteredException {
+ synchronized (mTransportLock) {
+ return getRegisteredTransportDescriptionOrThrowLocked(transportName)
+ .currentDestinationString;
+ }
+ }
+
+ /**
* Retrieve the data management label of {@code transportName}.
* @throws TransportNotRegisteredException if the transport is not registered.
*/
@@ -290,6 +297,18 @@
}
/**
+ * Retrieve the transport dir name of {@code transportComponent}.
+ * @throws TransportNotRegisteredException if the transport is not registered.
+ */
+ public String getTransportDirName(ComponentName transportComponent)
+ throws TransportNotRegisteredException {
+ synchronized (mTransportLock) {
+ return getRegisteredTransportDescriptionOrThrowLocked(transportComponent)
+ .transportDirName;
+ }
+ }
+
+ /**
* Execute {@code transportConsumer} for each registered transport passing the transport name.
* This is called with an internal lock held, ensuring that the transport will remain registered
* while {@code transportConsumer} is being executed. Don't do heavy operations in
@@ -315,23 +334,6 @@
return null;
}
- /**
- * Returns the transport name associated with {@param transportComponent} or {@code null} if not
- * found.
- */
- @Nullable
- public String getTransportName(ComponentName transportComponent) {
- synchronized (mTransportLock) {
- TransportDescription description =
- mRegisteredTransportsDescriptionMap.get(transportComponent);
- if (description == null) {
- Slog.e(TAG, "Trying to find name of unregistered transport " + transportComponent);
- return null;
- }
- return description.name;
- }
- }
-
@GuardedBy("mTransportLock")
@Nullable
private ComponentName getRegisteredTransportComponentLocked(String transportName) {
@@ -358,7 +360,6 @@
return description;
}
-
@GuardedBy("mTransportLock")
@Nullable
private Map.Entry<ComponentName, TransportDescription> getRegisteredTransportEntryLocked(
@@ -373,17 +374,35 @@
return null;
}
+ @GuardedBy("mTransportLock")
+ private TransportDescription getRegisteredTransportDescriptionOrThrowLocked(
+ ComponentName transportComponent) throws TransportNotRegisteredException {
+ TransportDescription description =
+ mRegisteredTransportsDescriptionMap.get(transportComponent);
+ if (description == null) {
+ throw new TransportNotRegisteredException(transportComponent);
+ }
+ return description;
+ }
+
@Nullable
public TransportClient getTransportClient(String transportName, String caller) {
+ try {
+ return getTransportClientOrThrow(transportName, caller);
+ } catch (TransportNotRegisteredException e) {
+ Slog.w(TAG, "Transport " + transportName + " not registered");
+ return null;
+ }
+ }
+
+ public TransportClient getTransportClientOrThrow(String transportName, String caller)
+ throws TransportNotRegisteredException {
synchronized (mTransportLock) {
ComponentName component = getRegisteredTransportComponentLocked(transportName);
if (component == null) {
- Slog.w(TAG, "Transport " + transportName + " not registered");
- return null;
+ throw new TransportNotRegisteredException(transportName);
}
- TransportDescription description = mRegisteredTransportsDescriptionMap.get(component);
- return mTransportClientManager.getTransportClient(
- component, description.transportDirName, caller);
+ return mTransportClientManager.getTransportClient(component, caller);
}
}
@@ -403,7 +422,25 @@
*/
@Nullable
public TransportClient getCurrentTransportClient(String caller) {
- return getTransportClient(mCurrentTransportName, caller);
+ synchronized (mTransportLock) {
+ return getTransportClient(mCurrentTransportName, caller);
+ }
+ }
+
+ /**
+ * Returns a {@link TransportClient} for the current transport or throws if not registered.
+ *
+ * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
+ * {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
+ * details.
+ * @return A {@link TransportClient}.
+ * @throws TransportNotRegisteredException if the transport is not registered.
+ */
+ public TransportClient getCurrentTransportClientOrThrow(String caller)
+ throws TransportNotRegisteredException {
+ synchronized (mTransportLock) {
+ return getTransportClientOrThrow(mCurrentTransportName, caller);
+ }
}
/**
@@ -492,29 +529,6 @@
return mCurrentTransportName;
}
- String selectTransport(String transport) {
- synchronized (mTransportLock) {
- String prevTransport = mCurrentTransportName;
- mCurrentTransportName = transport;
- return prevTransport;
- }
- }
-
- void ensureTransportReady(ComponentName transportComponent,
- TransportReadyCallback listener) {
- synchronized (mTransportLock) {
- TransportConnection conn = mValidTransports.get(transportComponent);
- if (conn == null) {
- listener.onFailure(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
- return;
- }
- // Transport can be unbound if the process hosting it crashed.
- conn.bindIfUnbound();
- conn.addListener(listener);
- }
- }
-
-
// This is for mocking, Mockito can't mock if package-protected and in the same package but
// different class loaders. Checked with the debugger and class loaders are different
// See https://github.com/mockito/mockito/issues/796
@@ -614,6 +628,90 @@
createSystemUserHandle());
}
+ String selectTransport(String transportName) {
+ synchronized (mTransportLock) {
+ String prevTransport = mCurrentTransportName;
+ mCurrentTransportName = transportName;
+ return prevTransport;
+ }
+ }
+
+ /**
+ * Tries to register the transport if not registered. If successful also selects the transport.
+ *
+ * @param transportComponent Host of the transport.
+ * @return One of {@link BackupManager#SUCCESS}, {@link BackupManager#ERROR_TRANSPORT_INVALID}
+ * or {@link BackupManager#ERROR_TRANSPORT_UNAVAILABLE}.
+ */
+ public int registerAndSelectTransport(ComponentName transportComponent) {
+ synchronized (mTransportLock) {
+ if (!mRegisteredTransportsDescriptionMap.containsKey(transportComponent)) {
+ int result = registerTransport(transportComponent);
+ if (result != BackupManager.SUCCESS) {
+ return result;
+ }
+ }
+
+ try {
+ selectTransport(getTransportName(transportComponent));
+ return BackupManager.SUCCESS;
+ } catch (TransportNotRegisteredException e) {
+ // Shouldn't happen because we are holding the lock
+ Slog.wtf(TAG, "Transport unexpectedly not registered");
+ return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
+ }
+ }
+ }
+
+ /**
+ * Tries to register transport represented by {@code transportComponent}.
+ *
+ * @param transportComponent Host of the transport that we want to register.
+ * @return One of {@link BackupManager#SUCCESS}, {@link BackupManager#ERROR_TRANSPORT_INVALID}
+ * or {@link BackupManager#ERROR_TRANSPORT_UNAVAILABLE}.
+ */
+ private int registerTransport(ComponentName transportComponent) {
+ String transportString = transportComponent.flattenToShortString();
+
+ String callerLogString = "TransportManager.registerTransport()";
+ TransportClient transportClient =
+ mTransportClientManager.getTransportClient(transportComponent, callerLogString);
+
+ final IBackupTransport transport;
+ try {
+ transport = transportClient.connectOrThrow(callerLogString);
+ } catch (TransportNotAvailableException e) {
+ Slog.e(TAG, "Couldn't connect to transport " + transportString + " for registration");
+ mTransportClientManager.disposeOfTransportClient(transportClient, callerLogString);
+ return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
+ }
+
+ EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 1);
+
+ int result;
+ if (isTransportValid(transport)) {
+ try {
+ registerTransport(transportComponent, transport);
+ // If registerTransport() hasn't thrown...
+ result = BackupManager.SUCCESS;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Transport " + transportString + " died while registering");
+ result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
+ }
+ } else {
+ Slog.w(TAG, "Can't register invalid transport " + transportString);
+ result = BackupManager.ERROR_TRANSPORT_INVALID;
+ }
+
+ mTransportClientManager.disposeOfTransportClient(transportClient, callerLogString);
+ if (result == BackupManager.SUCCESS) {
+ Slog.d(TAG, "Transport " + transportString + " registered");
+ } else {
+ EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 0);
+ }
+ return result;
+ }
+
/** If {@link RemoteException} is thrown the transport is guaranteed to not be registered. */
private void registerTransport(ComponentName transportComponent, IBackupTransport transport)
throws RemoteException {
@@ -630,11 +728,18 @@
}
}
+ private boolean isTransportValid(IBackupTransport transport) {
+ if (mTransportBoundListener == null) {
+ Slog.w(TAG, "setTransportBoundListener() not called, assuming transport invalid");
+ return false;
+ }
+ return mTransportBoundListener.onTransportBound(transport);
+ }
+
private class TransportConnection implements ServiceConnection {
// Hold mTransportLock to access these fields so as to provide a consistent view of them.
private volatile IBackupTransport mBinder;
- private final List<TransportReadyCallback> mListeners = new ArrayList<>();
private volatile String mTransportName;
private final ComponentName mTransportComponent;
@@ -656,15 +761,7 @@
mTransportName = mBinder.name();
// BackupManager requests some fields from the transport. If they are
// invalid, throw away this transport.
- final boolean valid;
- if (mTransportBoundListener != null) {
- valid = mTransportBoundListener.onTransportBound(mBinder);
- } else {
- Slog.w(TAG, "setTransportBoundListener() not called, assuming transport "
- + component + " valid");
- valid = true;
- }
- if (valid) {
+ if (isTransportValid(mBinder)) {
// We're now using the always-bound connection to do the registration but
// when we remove the always-bound code this will be in the first binding
// TODO: Move registration to first binding
@@ -682,9 +779,6 @@
if (success) {
Slog.d(TAG, "Bound to transport: " + componentShortString);
mBoundTransports.put(mTransportName, component);
- for (TransportReadyCallback listener : mListeners) {
- listener.onSuccess(mTransportName);
- }
// cancel rebinding on timeout for this component as we've already connected
mHandler.removeMessages(REBINDING_TIMEOUT_MSG, componentShortString);
} else {
@@ -696,11 +790,7 @@
mValidTransports.remove(component);
mEligibleTransports.remove(component);
mBinder = null;
- for (TransportReadyCallback listener : mListeners) {
- listener.onFailure(BackupManager.ERROR_TRANSPORT_INVALID);
- }
}
- mListeners.clear();
}
}
}
@@ -755,19 +845,6 @@
}
}
- private void addListener(TransportReadyCallback listener) {
- synchronized (mTransportLock) {
- if (mBinder == null) {
- // We are waiting for bind to complete. If mBinder is set to null after the bind
- // is complete due to transport being invalid, we won't find 'this' connection
- // object in mValidTransports list and this function can't be called.
- mListeners.add(listener);
- } else {
- listener.onSuccess(mTransportName);
- }
- }
- }
-
private long getRebindTimeout() {
final boolean isDeviceProvisioned = Settings.Global.getInt(
mContext.getContentResolver(),
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index a002334..c232241 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -560,16 +560,9 @@
}
backupManagerService.addBackupTrace("init required; rerunning");
try {
- final String name = backupManagerService.getTransportManager()
+ String name = backupManagerService.getTransportManager()
.getTransportName(mTransportClient.getTransportComponent());
- if (name != null) {
- backupManagerService.getPendingInits().add(name);
- } else {
- if (DEBUG) {
- Slog.w(TAG, "Couldn't find name of transport "
- + mTransportClient.getTransportComponent() + " for init");
- }
- }
+ backupManagerService.getPendingInits().add(name);
} catch (Exception e) {
Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
// swallow it and proceed; we don't rely on this
diff --git a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
index 84ca59b..140d7286 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
@@ -23,12 +23,14 @@
import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.TransportManager;
import com.android.server.backup.transport.TransportClient;
import java.io.File;
public class PerformClearTask implements Runnable {
private final RefactoredBackupManagerService mBackupManagerService;
+ private final TransportManager mTransportManager;
private final TransportClient mTransportClient;
private final PackageInfo mPackage;
private final OnTaskFinishedListener mListener;
@@ -37,6 +39,7 @@
TransportClient transportClient, PackageInfo packageInfo,
OnTaskFinishedListener listener) {
mBackupManagerService = backupManagerService;
+ mTransportManager = backupManagerService.getTransportManager();
mTransportClient = transportClient;
mPackage = packageInfo;
mListener = listener;
@@ -47,8 +50,9 @@
IBackupTransport transport = null;
try {
// Clear the on-device backup state to ensure a full backup next time
- File stateDir = new File(mBackupManagerService.getBaseStateDir(),
- mTransportClient.getTransportDirName());
+ String transportDirName =
+ mTransportManager.getTransportDirName(mTransportClient.getTransportComponent());
+ File stateDir = new File(mBackupManagerService.getBaseStateDir(), transportDirName);
File stateFile = new File(stateDir, mPackage.packageName);
stateFile.delete();
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index c624698..2f2af98 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -122,7 +122,9 @@
transportClientsToDisposeOf.add(transportClient);
Slog.i(TAG, "Initializing (wiping) backup transport storage: " + transportName);
- String transportDirName = transportClient.getTransportDirName();
+ String transportDirName =
+ mTransportManager.getTransportDirName(
+ transportClient.getTransportComponent());
EventLog.writeEvent(EventLogTags.BACKUP_START, transportDirName);
long startRealtime = SystemClock.elapsedRealtime();
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 86866dc..88f9ead 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -61,6 +61,7 @@
import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.TransportManager;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.utils.AppBackupUtils;
@@ -78,6 +79,7 @@
public class PerformUnifiedRestoreTask implements BackupRestoreTask {
private RefactoredBackupManagerService backupManagerService;
+ private final TransportManager mTransportManager;
// Transport client we're working with to do the restore
private final TransportClient mTransportClient;
@@ -164,6 +166,7 @@
int pmToken, boolean isFullSystemRestore, String[] filterSet,
OnTaskFinishedListener listener) {
this.backupManagerService = backupManagerService;
+ mTransportManager = backupManagerService.getTransportManager();
mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
mState = UnifiedRestoreState.INITIAL;
mStartRealtime = SystemClock.elapsedRealtime();
@@ -349,8 +352,9 @@
}
try {
- String transportDir = mTransportClient.getTransportDirName();
- mStateDir = new File(backupManagerService.getBaseStateDir(), transportDir);
+ String transportDirName =
+ mTransportManager.getTransportDirName(mTransportClient.getTransportComponent());
+ mStateDir = new File(backupManagerService.getBaseStateDir(), transportDirName);
// Fetch the current metadata from the dataset first
PackageInfo pmPackage = new PackageInfo();
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index 2c7a0eb..7bd9111 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -68,7 +68,6 @@
private final Intent mBindIntent;
private final String mIdentifier;
private final ComponentName mTransportComponent;
- private final String mTransportDirName;
private final Handler mListenerHandler;
private final String mPrefixForLog;
private final Object mStateLock = new Object();
@@ -87,13 +86,11 @@
Context context,
Intent bindIntent,
ComponentName transportComponent,
- String transportDirName,
String identifier) {
this(
context,
bindIntent,
transportComponent,
- transportDirName,
identifier,
new Handler(Looper.getMainLooper()));
}
@@ -103,12 +100,10 @@
Context context,
Intent bindIntent,
ComponentName transportComponent,
- String transportDirName,
String identifier,
Handler listenerHandler) {
mContext = context;
mTransportComponent = transportComponent;
- mTransportDirName = transportDirName;
mBindIntent = bindIntent;
mIdentifier = identifier;
mListenerHandler = listenerHandler;
@@ -122,10 +117,6 @@
return mTransportComponent;
}
- public String getTransportDirName() {
- return mTransportDirName;
- }
-
// Calls to onServiceDisconnected() or onBindingDied() turn TransportClient UNUSABLE. After one
// of these calls, if a binding happen again the new service can be a different instance. Since
// transports are stateful, we don't want a new instance responding for an old instance's state.
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
index bb550f6..1cbe7471 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
@@ -23,7 +23,6 @@
import android.content.Intent;
import android.util.Log;
-import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.TransportManager;
/**
@@ -48,17 +47,12 @@
* transportComponent}.
*
* @param transportComponent The {@link ComponentName} of the transport.
- * @param transportDirName The {@link String} returned by
- * {@link IBackupTransport#transportDirName()} at registration.
* @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
* {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
* details.
* @return A {@link TransportClient}.
*/
- public TransportClient getTransportClient(
- ComponentName transportComponent,
- String transportDirName,
- String caller) {
+ public TransportClient getTransportClient(ComponentName transportComponent, String caller) {
Intent bindIntent =
new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent);
synchronized (mTransportClientsLock) {
@@ -67,7 +61,6 @@
mContext,
bindIntent,
transportComponent,
- transportDirName,
Integer.toString(mTransportClientsCreated));
mTransportClientsCreated++;
TransportUtils.log(Log.DEBUG, TAG, caller, "Retrieving " + transportClient);
diff --git a/services/backup/java/com/android/server/backup/transport/TransportNotRegisteredException.java b/services/backup/java/com/android/server/backup/transport/TransportNotRegisteredException.java
index 26bf92c..02766de 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportNotRegisteredException.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportNotRegisteredException.java
@@ -16,6 +16,7 @@
package com.android.server.backup.transport;
+import android.content.ComponentName;
import android.util.AndroidException;
import com.android.server.backup.TransportManager;
@@ -32,4 +33,8 @@
public TransportNotRegisteredException(String transportName) {
super("Transport " + transportName + " not registered");
}
+
+ public TransportNotRegisteredException(ComponentName transportComponent) {
+ super("Transport for host " + transportComponent + " not registered");
+ }
}
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index d7cac77..dbf1a826 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -20,6 +20,8 @@
import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import android.annotation.Nullable;
+import android.app.backup.BackupTransport;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -27,7 +29,9 @@
import android.os.Process;
import android.util.Slog;
+import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.ArrayUtils;
+import com.android.server.backup.transport.TransportClient;
/**
* Utility methods wrapping operations on ApplicationInfo and PackageInfo.
@@ -71,6 +75,44 @@
return !appIsDisabled(app, pm);
}
+ /**
+ * Returns whether an app is eligible for backup at runtime. That is, the app has to:
+ * <ol>
+ * <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, PackageManager)}
+ * <li>Return false for {@link #appIsStopped(ApplicationInfo)}
+ * <li>Return false for {@link #appIsDisabled(ApplicationInfo, PackageManager)}
+ * <li>Be eligible for the transport via
+ * {@link BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)}
+ * </ol>
+ */
+ public static boolean appIsRunningAndEligibleForBackupWithTransport(
+ @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
+ try {
+ PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+ ApplicationInfo applicationInfo = packageInfo.applicationInfo;
+ if (!appIsEligibleForBackup(applicationInfo, pm)
+ || appIsStopped(applicationInfo)
+ || appIsDisabled(applicationInfo, pm)) {
+ return false;
+ }
+ if (transportClient != null) {
+ try {
+ IBackupTransport transport =
+ transportClient.connectOrThrow(
+ "AppBackupUtils.appIsEligibleForBackupAtRuntime");
+ return transport.isAppEligibleForBackup(
+ packageInfo, AppBackupUtils.appGetsFullBackup(packageInfo));
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
+ }
+ }
+ // If transport is not present we couldn't tell that the package is not eligible.
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
/** Avoid backups of 'disabled' apps. */
public static boolean appIsDisabled(ApplicationInfo app, PackageManager pm) {
switch (pm.getApplicationEnabledSetting(app.packageName)) {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 472723d..86063c3 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -149,6 +149,9 @@
private long mNextNonWakeup;
private long mLastWakeupSet;
private long mLastWakeup;
+ private long mLastTickSet;
+ private long mLastTickIssued; // elapsed
+ private long mLastTickReceived;
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
@@ -1159,12 +1162,12 @@
// ignored; both services live in system_server
}
publishBinderService(Context.ALARM_SERVICE, mService);
- mForceAppStandbyTracker.start();
}
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mForceAppStandbyTracker.start();
mConstants.start(getContext().getContentResolver());
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mLocalDeviceIdleController
@@ -1596,6 +1599,7 @@
pw.println();
mForceAppStandbyTracker.dump(pw, " ");
+ pw.println();
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
@@ -1607,8 +1611,12 @@
pw.println();
pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
- pw.print(" mLastTimeChangeRealtime=");
- TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
+ pw.print(" mLastTimeChangeRealtime="); pw.println(mLastTimeChangeRealtime);
+ pw.print(" mLastTickIssued=");
+ TimeUtils.formatDuration(mLastTickIssued - nowELAPSED, pw);
+ pw.println();
+ pw.print(" mLastTickReceived="); pw.println(sdf.format(new Date(mLastTickReceived)));
+ pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
pw.println();
if (!mInteractive) {
pw.print(" Time since non-interactive: ");
@@ -3284,6 +3292,9 @@
if (DEBUG_BATCH) {
Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
}
+ synchronized (mLock) {
+ mLastTickReceived = System.currentTimeMillis();
+ }
scheduleTimeTickEvent();
} else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
// Since the kernel does not keep track of DST, we need to
@@ -3309,6 +3320,11 @@
setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
null, Process.myUid(), "android");
+
+ // Finally, remember when we set the tick alarm
+ synchronized (mLock) {
+ mLastTickSet = currentTime;
+ }
}
public void scheduleDateChangedEvent() {
@@ -3660,6 +3676,11 @@
if (alarm.operation != null) {
// PendingIntent alarm
mSendCount++;
+
+ if (alarm.priorityClass.priority == PRIO_TICK) {
+ mLastTickIssued = nowELAPSED;
+ }
+
try {
alarm.operation.send(getContext(), 0,
mBackgroundIntent.putExtra(
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 04d292f..dcb0fab 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -293,10 +293,13 @@
private void updateBatteryWarningLevelLocked() {
final ContentResolver resolver = mContext.getContentResolver();
- int defWarnLevel = mContext.getResources().getInteger(
+ final int defWarnLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
- mLowBatteryWarningLevel = Settings.Global.getInt(resolver,
+ final int lowPowerModeTriggerLevel = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
+
+ mLowBatteryWarningLevel = Math.min(defWarnLevel, lowPowerModeTriggerLevel);
+
if (mLowBatteryWarningLevel == 0) {
mLowBatteryWarningLevel = defWarnLevel;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 86b0164..63ee9fa 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -130,6 +130,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
+import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
@@ -233,8 +234,6 @@
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
- private int mNumDnsEntries;
-
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
@@ -408,6 +407,7 @@
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
final private NetworkStateTrackerHandler mTrackerHandler;
+ private final DnsManager mDnsManager;
private boolean mSystemReady;
private Intent mInitialBroadcast;
@@ -880,6 +880,8 @@
mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
mMultinetworkPolicyTracker.start();
+
+ mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
}
private Tethering makeTethering() {
@@ -1826,24 +1828,6 @@
}
}
- private void flushVmDnsCache() {
- /*
- * Tell the VMs to toss their DNS caches
- */
- Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- /*
- * Connectivity events can happen before boot has completed ...
- */
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@Override
public int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = mSystemProperties.get(
@@ -4586,41 +4570,17 @@
return; // no updating necessary
}
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
+
Collection<InetAddress> dnses = newLp.getDnsServers();
if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
try {
- mNetd.setDnsConfigurationForNetwork(
- netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+ mDnsManager.setDnsConfigurationForNetwork(
+ netId, dnses, newLp.getDomains(), isDefaultNetwork);
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
- flushVmDnsCache();
- }
-
- private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
- int last = 0;
- for (InetAddress dns : dnses) {
- ++last;
- setNetDnsProperty(last, dns.getHostAddress());
- }
- for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- setNetDnsProperty(i, "");
- }
- mNumDnsEntries = last;
- }
-
- private void setNetDnsProperty(int which, String value) {
- final String key = "net.dns" + which;
- // Log and forget errors setting unsupported properties.
- try {
- mSystemProperties.set(key, value);
- } catch (Exception e) {
- Log.e(TAG, "Error setting unsupported net.dns property: ", e);
- }
}
private String getNetworkPermission(NetworkCapabilities nc) {
@@ -4893,7 +4853,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+ mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6f697c4..985f16d 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -795,64 +795,65 @@
Slog.e(TAG, "Bad device idle settings", e);
}
- LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(
+ LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
- LIGHT_PRE_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_PRE_IDLE_TIMEOUT,
+ LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT,
!COMPRESS_TIME ? 10 * 60 * 1000L : 30 * 1000L);
- LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
+ LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT,
!COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
2f);
- LIGHT_MAX_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_MAX_IDLE_TIMEOUT,
+ LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT,
!COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
- LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getLong(
+ LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis(
KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
!COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
- LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getLong(
+ LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis(
KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
!COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
- MIN_LIGHT_MAINTENANCE_TIME = mParser.getLong(
+ MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis(
KEY_MIN_LIGHT_MAINTENANCE_TIME,
!COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
- MIN_DEEP_MAINTENANCE_TIME = mParser.getLong(
+ MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis(
KEY_MIN_DEEP_MAINTENANCE_TIME,
!COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
- INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
+ INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
- SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
+ SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
!DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
- LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
+ LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
!DEBUG ? 30 * 1000L : 15 * 1000L);
LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
- MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
+ MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
- IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
+ IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
+ KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? idleAfterInactiveTimeout
: (idleAfterInactiveTimeout / 10));
- IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
+ IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT,
!COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
- MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
+ MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT,
!COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
2f);
- IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
+ IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
!COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
- MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
+ MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
!COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
2f);
- MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
+ MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM,
!COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
- MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
- MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
- SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
- NOTIFICATION_WHITELIST_DURATION = mParser.getLong(
+ NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 6174aec..8361132 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -261,6 +261,10 @@
2756 fstrim_finish (time|2|3)
# ---------------------------
+# Job scheduler
+# ---------------------------
+8000 job_deferred_execution (time|2|3)
+
# AudioService.java
# ---------------------------
40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index 61d3833..8776f3a 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -33,8 +34,10 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.ArraySet;
import android.util.Pair;
+import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
@@ -59,15 +62,16 @@
* - Global "force all apps standby" mode enforced by battery saver.
*
* TODO: In general, we can reduce the number of callbacks by checking all signals before sending
- * each callback. For example, even when an UID comes into the foreground, if it wasn't
- * originally restricted, then there's no need to send an event.
- * Doing this would be error-prone, so we punt it for now, but we should revisit it later.
+ * each callback. For example, even when an UID comes into the foreground, if it wasn't
+ * originally restricted, then there's no need to send an event.
+ * Doing this would be error-prone, so we punt it for now, but we should revisit it later.
*
* Test:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+ * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
*/
public class ForceAppStandbyTracker {
private static final String TAG = "ForceAppStandbyTracker";
+ private static final boolean DEBUG = false;
@GuardedBy("ForceAppStandbyTracker.class")
private static ForceAppStandbyTracker sInstance;
@@ -107,7 +111,43 @@
boolean mStarted;
@GuardedBy("mLock")
- boolean mForceAllAppsStandby;
+ boolean mForceAllAppsStandby; // True if device is in extreme battery saver mode
+
+ @GuardedBy("mLock")
+ boolean mForcedAppStandbyEnabled; // True if the forced app standby feature is enabled
+
+ private class FeatureFlagObserver extends ContentObserver {
+ FeatureFlagObserver() {
+ super(null);
+ }
+
+ void register() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
+ false, this);
+ }
+
+ boolean isForcedAppStandbyEnabled() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled = isForcedAppStandbyEnabled();
+ synchronized (mLock) {
+ if (mForcedAppStandbyEnabled == enabled) {
+ return;
+ }
+ mForcedAppStandbyEnabled = enabled;
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
+ }
+ }
+ mHandler.notifyFeatureFlagChanged();
+ }
+ }
public static abstract class Listener {
/**
@@ -246,6 +286,9 @@
mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
+ final FeatureFlagObserver flagObserver = new FeatureFlagObserver();
+ flagObserver.register();
+ mForcedAppStandbyEnabled = flagObserver.isForcedAppStandbyEnabled();
try {
mIActivityManager.registerUidObserver(new UidObserver(),
@@ -364,7 +407,7 @@
*/
boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
boolean restricted) {
- final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
+ final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
final boolean wasRestricted = index >= 0;
if (wasRestricted == restricted) {
return false;
@@ -418,25 +461,30 @@
}
private final class UidObserver extends IUidObserver.Stub {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override
+ public void onUidStateChanged(int uid, int procState, long procStateSeq) {
}
- @Override public void onUidGone(int uid, boolean disabled) {
+ @Override
+ public void onUidGone(int uid, boolean disabled) {
uidToBackground(uid, /*remove=*/ true);
}
- @Override public void onUidActive(int uid) {
+ @Override
+ public void onUidActive(int uid) {
uidToForeground(uid);
}
- @Override public void onUidIdle(int uid, boolean disabled) {
+ @Override
+ public void onUidIdle(int uid, boolean disabled) {
// Just to avoid excessive memcpy, don't remove from the array in this case.
uidToBackground(uid, /*remove=*/ false);
}
- @Override public void onUidCachedChanged(int uid, boolean cached) {
+ @Override
+ public void onUidCachedChanged(int uid, boolean cached) {
}
- };
+ }
private final class AppOpsWatcher extends IAppOpsCallback.Stub {
@Override
@@ -481,8 +529,8 @@
private static final int MSG_ALL_WHITELIST_CHANGED = 4;
private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
private static final int MSG_FORCE_ALL_CHANGED = 6;
-
private static final int MSG_USER_REMOVED = 7;
+ private static final int MSG_FEATURE_FLAG_CHANGED = 8;
public MyHandler(Looper looper) {
super(looper);
@@ -491,6 +539,7 @@
public void notifyUidForegroundStateChanged(int uid) {
obtainMessage(MSG_UID_STATE_CHANGED, uid, 0).sendToTarget();
}
+
public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
}
@@ -511,12 +560,16 @@
obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
}
+ public void notifyFeatureFlagChanged() {
+ obtainMessage(MSG_FEATURE_FLAG_CHANGED).sendToTarget();
+ }
+
public void doUserRemoved(int userId) {
obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
}
@Override
- public void dispatchMessage(Message msg) {
+ public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_REMOVED:
handleUserRemoved(msg.arg1);
@@ -562,6 +615,19 @@
l.onForceAllAppsStandbyChanged(sender);
}
return;
+ case MSG_FEATURE_FLAG_CHANGED:
+ // Feature flag for forced app standby changed.
+ final boolean unblockAlarms;
+ synchronized (mLock) {
+ unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
+ }
+ for (Listener l: cloneListeners()) {
+ l.updateAllJobs();
+ if (unblockAlarms) {
+ l.unblockAllUnrestrictedAlarms();
+ }
+ }
+ return;
case MSG_USER_REMOVED:
handleUserRemoved(msg.arg1);
return;
@@ -701,7 +767,7 @@
return true;
}
- return isRunAnyRestrictedLocked(uid, packageName);
+ return mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName);
}
}
@@ -766,6 +832,9 @@
public void dump(PrintWriter pw, String indent) {
synchronized (mLock) {
pw.print(indent);
+ pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
+
+ pw.print(indent);
pw.print("Force all apps standby: ");
pw.println(isForceAllAppsStandbyEnabled());
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 989cb88..02cfe3d 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -52,6 +52,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -102,8 +103,14 @@
/* Binder context for this service */
private final Context mContext;
- /** Should be a never-repeating global ID for resources */
- private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0);
+ /**
+ * The next non-repeating global ID for tracking resources between users, this service,
+ * and kernel data structures. Accessing this variable is not thread safe, so it is
+ * only read or modified within blocks synchronized on IpSecService.this. We want to
+ * avoid -1 (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it).
+ */
+ @GuardedBy("IpSecService.this")
+ private int mNextResourceId = 1;
interface IpSecServiceConfiguration {
INetd getNetdInstance() throws RemoteException;
@@ -856,7 +863,7 @@
checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
String localAddress = "";
@@ -979,7 +986,7 @@
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
FileDescriptor sockFd = null;
try {
if (!userRecord.mSocketQuotaTracker.isAvailable()) {
@@ -1024,6 +1031,30 @@
releaseResource(userRecord.mEncapSocketRecords, resourceId);
}
+ @VisibleForTesting
+ void validateAlgorithms(IpSecConfig config, int direction) throws IllegalArgumentException {
+ IpSecAlgorithm auth = config.getAuthentication(direction);
+ IpSecAlgorithm crypt = config.getEncryption(direction);
+ IpSecAlgorithm aead = config.getAuthenticatedEncryption(direction);
+
+ // Validate the algorithm set
+ Preconditions.checkArgument(
+ aead != null || crypt != null || auth != null,
+ "No Encryption or Authentication algorithms specified");
+ Preconditions.checkArgument(
+ auth == null || auth.isAuthentication(),
+ "Unsupported algorithm for Authentication");
+ Preconditions.checkArgument(
+ crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption");
+ Preconditions.checkArgument(
+ aead == null || aead.isAead(),
+ "Unsupported algorithm for Authenticated Encryption");
+ Preconditions.checkArgument(
+ aead == null || (auth == null && crypt == null),
+ "Authenticated Encryption is mutually exclusive with other Authentication "
+ + "or Encryption algorithms");
+ }
+
/**
* Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
* IllegalArgumentException if they are not.
@@ -1073,17 +1104,7 @@
}
for (int direction : DIRECTIONS) {
- IpSecAlgorithm crypt = config.getEncryption(direction);
- IpSecAlgorithm auth = config.getAuthentication(direction);
- IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction);
- if (authenticatedEncryption == null && crypt == null && auth == null) {
- throw new IllegalArgumentException(
- "No Encryption or Authentication algorithms specified");
- } else if (authenticatedEncryption != null && (auth != null || crypt != null)) {
- throw new IllegalArgumentException(
- "Authenticated Encryption is mutually"
- + " exclusive with other Authentication or Encryption algorithms");
- }
+ validateAlgorithms(config, direction);
// Retrieve SPI record; will throw IllegalArgumentException if not found
userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction));
@@ -1102,7 +1123,7 @@
IpSecConfig c, IBinder binder) throws RemoteException {
checkIpSecConfig(c);
checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
- int resourceId = mNextResourceId.getAndIncrement();
+ final int resourceId = mNextResourceId++;
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 57c992f..ea748db 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -2254,6 +2254,64 @@
}
}
+ /**
+ * Provides an interface to inject and set the last location if location is not available
+ * currently.
+ *
+ * This helps in cases where the product (Cars for example) has saved the last known location
+ * before powering off. This interface lets the client inject the saved location while the GPS
+ * chipset is getting its first fix, there by improving user experience.
+ *
+ * @param location - Location object to inject
+ * @return true if update was successful, false if not
+ */
+ @Override
+ public boolean injectLocation(Location location) {
+ mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
+ "Location Hardware permission not granted to inject location");
+ mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
+ "Access Fine Location permission not granted to inject Location");
+
+ if (location == null) {
+ if (D) {
+ Log.d(TAG, "injectLocation(): called with null location");
+ }
+ return false;
+ }
+ LocationProviderInterface p = null;
+ String provider = location.getProvider();
+ if (provider != null) {
+ p = mProvidersByName.get(provider);
+ }
+ if (p == null) {
+ if (D) {
+ Log.d(TAG, "injectLocation(): unknown provider");
+ }
+ return false;
+ }
+ synchronized (mLock) {
+ if (!isAllowedByCurrentUserSettingsLocked(provider)) {
+ if (D) {
+ Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
+ }
+ return false;
+ } else {
+ // NOTE: If last location is already available, location is not injected. If
+ // provider's normal source (like a GPS chipset) have already provided an output,
+ // there is no need to inject this location.
+ if (mLastLocation.get(provider) == null) {
+ updateLastLocationLocked(location, provider);
+ } else {
+ if (D) {
+ Log.d(TAG, "injectLocation(): Location exists. Not updating");
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
@Override
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
String packageName) {
@@ -2614,30 +2672,18 @@
private void handleLocationChangedLocked(Location location, boolean passive) {
if (D) Log.d(TAG, "incoming location: " + location);
-
long now = SystemClock.elapsedRealtime();
String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
-
// Skip if the provider is unknown.
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) return;
-
- // Update last known locations
- Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
- Location lastNoGPSLocation;
+ updateLastLocationLocked(location, provider);
+ // mLastLocation should have been updated from the updateLastLocationLocked call above.
Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) {
- lastLocation = new Location(provider);
- mLastLocation.put(provider, lastLocation);
- } else {
- lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
- if (noGPSLocation == null && lastNoGPSLocation != null) {
- // New location has no no-GPS location: adopt last no-GPS location. This is set
- // directly into location because we do not want to notify COARSE clients.
- location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
- }
+ Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
+ return;
}
- lastLocation.set(location);
// Update last known coarse interval location if enough time has passed.
Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
@@ -2653,7 +2699,7 @@
// Don't ever return a coarse location that is more recent than the allowed update
// interval (i.e. don't allow an app to keep registering and unregistering for
// location updates to overcome the minimum interval).
- noGPSLocation =
+ Location noGPSLocation =
lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
// Skip if there are no UpdateRecords for this provider.
@@ -2778,6 +2824,30 @@
}
}
+ /**
+ * Updates last location with the given location
+ *
+ * @param location new location to update
+ * @param provider Location provider to update for
+ */
+ private void updateLastLocationLocked(Location location, String provider) {
+ Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ Location lastNoGPSLocation;
+ Location lastLocation = mLastLocation.get(provider);
+ if (lastLocation == null) {
+ lastLocation = new Location(provider);
+ mLastLocation.put(provider, lastLocation);
+ } else {
+ lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ if (noGPSLocation == null && lastNoGPSLocation != null) {
+ // New location has no no-GPS location: adopt last no-GPS location. This is set
+ // directly into location because we do not want to notify COARSE clients.
+ location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
+ }
+ }
+ lastLocation.set(location);
+ }
+
private class LocationWorkerHandler extends Handler {
public LocationWorkerHandler(Looper looper) {
super(looper, null, true);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8a15ded..40e6d26 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
@@ -209,12 +210,6 @@
public static final int StrictCleartext = 617;
}
- /* Defaults for resolver parameters. */
- public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
- public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
- public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
- public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
-
/**
* String indicating a softap command.
*/
@@ -1768,6 +1763,8 @@
@Override
public boolean setDataSaverModeEnabled(boolean enable) {
+ mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
+
if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
synchronized (mQuotaLock) {
if (mDataSaverMode == enable) {
@@ -1947,66 +1944,14 @@
}
@Override
- public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
+ public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains,
+ int[] params, boolean useTls, String tlsHostname) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final ContentResolver cr = mContext.getContentResolver();
-
- int sampleValidity = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- if (sampleValidity < 0 || sampleValidity > 65535) {
- Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
- }
-
- int successThreshold = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- if (successThreshold < 0 || successThreshold > 100) {
- Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
- }
-
- int minSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
- int maxSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
- if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
- Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
- "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
- DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
- minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
- maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
- }
-
- final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
- final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
- final boolean useTls = shouldUseTls(cr);
- // TODO: Populate tlsHostname once it's decided how the hostname's IP
- // addresses will be resolved:
- //
- // [1] network-provided DNS servers are included here with the
- // hostname and netd will use the network-provided servers to
- // resolve the hostname and fix up its internal structures, or
- //
- // [2] network-provided DNS servers are included here without the
- // hostname, the ConnectivityService layer resolves the given
- // hostname, and then reconfigures netd with this information.
- //
- // In practice, there will always be a need for ConnectivityService or
- // the captive portal app to use the network-provided services to make
- // some queries. This argues in favor of [1], in concert with another
- // mechanism, perhaps setting a high bit in the netid, to indicate
- // via existing DNS APIs which set of servers (network-provided or
- // non-network-provided private DNS) should be queried.
- final String tlsHostname = "";
final String[] tlsFingerprints = new String[0];
try {
- mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
- useTls, tlsHostname, tlsFingerprints);
+ mNetdService.setResolverConfiguration(
+ netId, servers, domains, params, useTls, tlsHostname, tlsFingerprints);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 90822d1..dc2f2a5 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -96,6 +96,7 @@
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
+import android.util.DataUnit;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -2190,7 +2191,7 @@
}
try {
- mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
+ mVold.fdeEnable(type, password, 0);
} catch (Exception e) {
Slog.wtf(TAG, e);
return -1;
@@ -3508,8 +3509,8 @@
pw.print(") total size: ");
pw.print(pair.second);
pw.print(" (");
- pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
- pw.println(" GB)");
+ pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
+ pw.println(" MiB)");
}
pw.println("Force adoptable: " + mForceAdoptable);
pw.println();
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 0e51fda..c1cda98 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -26,6 +26,7 @@
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.hardware.vibrator.V1_0.Constants.EffectStrength;
+import android.icu.text.DateFormat;
import android.media.AudioManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
@@ -62,6 +63,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.Date;
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
@@ -69,6 +71,8 @@
private static final boolean DEBUG = false;
private static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
+ private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = { 0, 30, 100, 30 };
+
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
private final boolean mAllowPriorityVibrationsInLowPowerMode;
@@ -110,7 +114,12 @@
private class Vibration implements IBinder.DeathRecipient {
private final IBinder mToken;
private final VibrationEffect mEffect;
+ // Start time in CLOCK_BOOTTIME base.
private final long mStartTime;
+ // Start time in unix epoch time. Only to be used for debugging purposes and to correlate
+ // with other system events, any duration calculations should be done use mStartTime so as
+ // not to be affected by discontinuities created by RTC adjustments.
+ private final long mStartTimeDebug;
private final int mUsageHint;
private final int mUid;
private final String mOpPkg;
@@ -119,7 +128,8 @@
int usageHint, int uid, String opPkg) {
mToken = token;
mEffect = effect;
- mStartTime = SystemClock.uptimeMillis();
+ mStartTime = SystemClock.elapsedRealtime();
+ mStartTimeDebug = System.currentTimeMillis();
mUsageHint = usageHint;
mUid = uid;
mOpPkg = opPkg;
@@ -153,18 +163,22 @@
return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg))
&& !repeating;
}
+
+ public VibrationInfo toInfo() {
+ return new VibrationInfo(mStartTimeDebug, mEffect, mUsageHint, mUid, mOpPkg);
+ }
}
private static class VibrationInfo {
- private final long mStartTime;
+ private final long mStartTimeDebug;
private final VibrationEffect mEffect;
private final int mUsageHint;
private final int mUid;
private final String mOpPkg;
- public VibrationInfo(long startTime, VibrationEffect effect,
+ public VibrationInfo(long startTimeDebug, VibrationEffect effect,
int usageHint, int uid, String opPkg) {
- mStartTime = startTime;
+ mStartTimeDebug = startTimeDebug;
mEffect = effect;
mUsageHint = usageHint;
mUid = uid;
@@ -174,8 +188,8 @@
@Override
public String toString() {
return new StringBuilder()
- .append(", startTime: ")
- .append(mStartTime)
+ .append("startTime: ")
+ .append(DateFormat.getDateTimeInstance().format(new Date(mStartTimeDebug)))
.append(", effect: ")
.append(mEffect)
.append(", usageHint: ")
@@ -225,7 +239,7 @@
com.android.internal.R.array.config_virtualKeyVibePattern);
VibrationEffect clickEffect = createEffect(clickEffectTimings);
VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
- new long[] {0, 30, 100, 30} /*timings*/, -1);
+ DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS, -1 /*repeatIndex*/);
long[] tickEffectTimings = getLongIntArray(context.getResources(),
com.android.internal.R.array.config_clockTickVibePattern);
VibrationEffect tickEffect = createEffect(tickEffectTimings);
@@ -392,17 +406,7 @@
}
Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
-
- // Only link against waveforms since they potentially don't have a finish if
- // they're repeating. Let other effects just play out until they're done.
- if (effect instanceof VibrationEffect.Waveform) {
- try {
- token.linkToDeath(vib, 0);
- } catch (RemoteException e) {
- return;
- }
- }
-
+ linkVibration(vib);
long ident = Binder.clearCallingIdentity();
try {
@@ -430,8 +434,7 @@
if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
mPreviousVibrations.removeFirst();
}
- mPreviousVibrations.addLast(new VibrationInfo(
- vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
+ mPreviousVibrations.addLast(vib.toInfo());
}
@Override // Binder call
@@ -589,10 +592,23 @@
AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
mCurrentVibration.mOpPkg);
} catch (RemoteException e) { }
+ unlinkVibration(mCurrentVibration);
mCurrentVibration = null;
}
}
+ private void linkVibration(Vibration vib) {
+ // Only link against waveforms since they potentially don't have a finish if
+ // they're repeating. Let other effects just play out until they're done.
+ if (vib.mEffect instanceof VibrationEffect.Waveform) {
+ try {
+ vib.mToken.linkToDeath(vib, 0);
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+ }
+
private void unlinkVibration(Vibration vib) {
if (vib.mEffect instanceof VibrationEffect.Waveform) {
vib.mToken.unlinkToDeath(vib, 0);
@@ -742,8 +758,7 @@
synchronized (mInputDeviceVibrators) {
VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
// Input devices don't support prebaked effect, so skip trying it with them.
- final int vibratorCount = mInputDeviceVibrators.size();
- if (vibratorCount == 0) {
+ if (mInputDeviceVibrators.isEmpty()) {
long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
if (timeout > 0) {
noteVibratorOnLocked(vib.mUid, timeout);
@@ -753,12 +768,11 @@
if (!prebaked.shouldFallback()) {
return 0;
}
- final int id = prebaked.getId();
- if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) {
+ VibrationEffect effect = getFallbackEffect(prebaked.getId());
+ if (effect == null) {
Slog.w(TAG, "Failed to play prebaked effect, no fallback");
return 0;
}
- VibrationEffect effect = mFallbackEffects[id];
Vibration fallbackVib =
new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
startVibrationInnerLocked(fallbackVib);
@@ -766,6 +780,13 @@
return 0;
}
+ private VibrationEffect getFallbackEffect(int effectId) {
+ if (effectId < 0 || effectId >= mFallbackEffects.length) {
+ return null;
+ }
+ return mFallbackEffects[effectId];
+ }
+
private void noteVibratorOnLocked(int uid, long millis) {
try {
mBatteryStatsService.noteVibratorOn(uid, millis);
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index af5cf1e..e38148c 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -556,10 +556,10 @@
return stack == getTopStack();
}
- boolean isTopFullscreenStack(ActivityStack stack) {
+ boolean isTopNotPinnedStack(ActivityStack stack) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack current = mStacks.get(i);
- if (current.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ if (!current.inPinnedWindowingMode()) {
return current == stack;
}
}
diff --git a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java b/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
similarity index 68%
rename from services/core/java/com/android/server/am/LaunchingActivityPositioner.java
rename to services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
index 793884d..f44ee7a 100644
--- a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java
+++ b/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
@@ -19,23 +19,25 @@
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
-import com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner;
+
+import com.android.server.am.LaunchParamsController.LaunchParams;
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
/**
- * An implementation of {@link LaunchingBoundsPositioner}, which applies the launch bounds specified
+ * An implementation of {@link LaunchParamsModifier}, which applies the launch bounds specified
* inside {@link ActivityOptions#getLaunchBounds()}.
*/
-public class LaunchingActivityPositioner implements LaunchingBoundsPositioner {
+public class ActivityLaunchParamsModifier implements LaunchParamsModifier {
private final ActivityStackSupervisor mSupervisor;
- LaunchingActivityPositioner(ActivityStackSupervisor activityStackSupervisor) {
+ ActivityLaunchParamsModifier(ActivityStackSupervisor activityStackSupervisor) {
mSupervisor = activityStackSupervisor;
}
@Override
- public int onCalculateBounds(TaskRecord task, ActivityInfo.WindowLayout layout,
- ActivityRecord activity, ActivityRecord source,
- ActivityOptions options, Rect current, Rect result) {
+ public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
+ ActivityRecord activity, ActivityRecord source, ActivityOptions options,
+ LaunchParams currentParams, LaunchParams outParams) {
// We only care about figuring out bounds for activities.
if (activity == null) {
return RESULT_SKIP;
@@ -43,7 +45,7 @@
// Activity must be resizeable in the specified task.
if (!(mSupervisor.canUseActivityOptionsLaunchBounds(options)
- && (activity.isResizeable() || (task != null && task.isResizeable())))) {
+ && (activity.isResizeable() || (task != null && task.isResizeable())))) {
return RESULT_SKIP;
}
@@ -54,7 +56,7 @@
return RESULT_SKIP;
}
- result.set(bounds);
+ outParams.mBounds.set(bounds);
// When this is the most explicit position specification so we should not allow further
// modification of the position.
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index b3a596c..0d6d2bd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -77,8 +77,8 @@
private static final long DEFAULT_CONTENT_PROVIDER_RETAIN_TIME = 20*1000;
private static final long DEFAULT_GC_TIMEOUT = 5*1000;
private static final long DEFAULT_GC_MIN_INTERVAL = 60*1000;
- private static final long DEFAULT_FULL_PSS_MIN_INTERVAL = 10*60*1000;
- private static final long DEFAULT_FULL_PSS_LOWERED_INTERVAL = 2*60*1000;
+ private static final long DEFAULT_FULL_PSS_MIN_INTERVAL = 20*60*1000;
+ private static final long DEFAULT_FULL_PSS_LOWERED_INTERVAL = 5*60*1000;
private static final long DEFAULT_POWER_CHECK_INTERVAL = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
private static final int DEFAULT_POWER_CHECK_MAX_CPU_1 = 25;
private static final int DEFAULT_POWER_CHECK_MAX_CPU_2 = 25;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5936ce1..6565187 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2521,13 +2521,15 @@
}
}
if (proc != null) {
+ long startTime = SystemClock.currentThreadTimeMillis();
long pss = Debug.getPss(pid, tmp, null);
+ long endTime = SystemClock.currentThreadTimeMillis();
synchronized (ActivityManagerService.this) {
if (pss != 0 && proc.thread != null && proc.setProcState == procState
&& proc.pid == pid && proc.lastPssTime == lastPssTime) {
num++;
recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
- SystemClock.uptimeMillis());
+ endTime-startTime, SystemClock.uptimeMillis());
}
}
}
@@ -2695,6 +2697,13 @@
}
@Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mService.mBatteryStatsService.systemServicesReady();
+ }
+ }
+
+ @Override
public void onCleanupUser(int userId) {
mService.mBatteryStatsService.onCleanupUser(userId);
}
@@ -6539,13 +6548,17 @@
}
}
infos[i] = new Debug.MemoryInfo();
+ long startTime = SystemClock.currentThreadTimeMillis();
Debug.getMemoryInfo(pids[i], infos[i]);
+ long endTime = SystemClock.currentThreadTimeMillis();
if (proc != null) {
synchronized (this) {
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
- infos[i].getTotalUss(), false, proc.pkgList);
+ infos[i].getTotalUss(), false,
+ ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime,
+ proc.pkgList);
}
}
}
@@ -6567,12 +6580,15 @@
}
}
long[] tmpUss = new long[1];
+ long startTime = SystemClock.currentThreadTimeMillis();
pss[i] = Debug.getPss(pids[i], tmpUss, null);
+ long endTime = SystemClock.currentThreadTimeMillis();
if (proc != null) {
synchronized (this) {
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
- proc.baseProcessTracker.addPss(pss[i], tmpUss[0], false, proc.pkgList);
+ proc.baseProcessTracker.addPss(pss[i], tmpUss[0], false,
+ ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList);
}
}
}
@@ -12245,6 +12261,7 @@
mConstants.start(mContext.getContentResolver());
mCoreSettingsObserver = new CoreSettingsObserver(this);
mFontScaleSettingObserver = new FontScaleSettingObserver();
+ GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());
// Now that the settings provider is published we can consider sending
// in a rescue party.
@@ -14158,7 +14175,7 @@
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord proc = mLruProcesses.get(i);
if (proc.notCachedSinceIdle) {
- if (proc.setProcState >= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ if (proc.setProcState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
&& proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
if (doKilling && proc.initialIdlePss != 0
&& proc.lastPss > ((proc.initialIdlePss*3)/2)) {
@@ -14875,6 +14892,7 @@
(process != null && process.info != null) ?
(process.info.isInstantApp() ? 1 : 0) : -1,
activity != null ? activity.shortComponentName : null,
+ activity != null ? activity.packageName : null,
process != null ? (process.isInterestingToUserLocked() ? 1 : 0) : -1);
// Rate-limit how often we're willing to do the heavy lifting below to
@@ -17659,11 +17677,20 @@
if (mi == null) {
mi = new Debug.MemoryInfo();
}
+ final int reportType;
+ final long startTime;
+ final long endTime;
if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
+ reportType = ProcessStats.ADD_PSS_EXTERNAL_SLOW;
+ startTime = SystemClock.currentThreadTimeMillis();
Debug.getMemoryInfo(pid, mi);
+ endTime = SystemClock.currentThreadTimeMillis();
hasSwapPss = mi.hasSwappedOutPss;
} else {
+ reportType = ProcessStats.ADD_PSS_EXTERNAL;
+ startTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
+ endTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPrivateDirty = (int)tmpLong[0];
}
if (opts.dumpDetails) {
@@ -17706,7 +17733,8 @@
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true, r.pkgList);
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+ reportType, endTime-startTime, r.pkgList);
}
}
@@ -18149,11 +18177,20 @@
if (mi == null) {
mi = new Debug.MemoryInfo();
}
+ final int reportType;
+ final long startTime;
+ final long endTime;
if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
+ reportType = ProcessStats.ADD_PSS_EXTERNAL_SLOW;
+ startTime = SystemClock.currentThreadTimeMillis();
Debug.getMemoryInfo(pid, mi);
+ endTime = SystemClock.currentThreadTimeMillis();
hasSwapPss = mi.hasSwappedOutPss;
} else {
+ reportType = ProcessStats.ADD_PSS_EXTERNAL;
+ startTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPss = (int) Debug.getPss(pid, tmpLong, null);
+ endTime = SystemClock.currentThreadTimeMillis();
mi.dalvikPrivateDirty = (int) tmpLong[0];
}
if (opts.dumpDetails) {
@@ -18192,7 +18229,8 @@
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true, r.pkgList);
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+ reportType, endTime-startTime, r.pkgList);
}
}
@@ -21382,7 +21420,7 @@
mAppWarnings.onDensityChanged();
killAllBackgroundProcessesExcept(N,
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
}
}
@@ -22356,6 +22394,7 @@
// to the top state.
switch (procState) {
case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+ case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
// Something else is keeping it at this level, just leave it.
break;
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
@@ -22454,11 +22493,12 @@
* Record new PSS sample for a process.
*/
void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
- long now) {
+ long pssDuration, long now) {
EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
swapPss * 1024);
proc.lastPssTime = now;
- proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
+ proc.baseProcessTracker.addPss(pss, uss, true, ProcessStats.ADD_PSS_INTERNAL,
+ pssDuration, proc.pkgList);
if (DEBUG_PSS) Slog.d(TAG_PSS,
"PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+ " state=" + ProcessList.makeProcStateString(procState));
@@ -22953,8 +22993,11 @@
// the data right when a process is transitioning between process
// states, which well tend to give noisy data.
long start = SystemClock.uptimeMillis();
+ long startTime = SystemClock.currentThreadTimeMillis();
long pss = Debug.getPss(app.pid, mTmpLong, null);
- recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1], now);
+ long endTime = SystemClock.currentThreadTimeMillis();
+ recordPssSampleLocked(app, app.curProcState, pss, endTime-startTime,
+ mTmpLong[0], mTmpLong[1], now);
mPendingPssProcesses.remove(app);
Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
+ " to " + app.curProcState + ": "
@@ -23189,7 +23232,7 @@
// To avoid some abuse patterns, we are going to be careful about what we consider
// to be an app interaction. Being the top activity doesn't count while the display
// is sleeping, nor do short foreground services.
- if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+ if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP) {
isInteraction = true;
app.fgInteractionTime = 0;
} else if (app.curProcState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -24706,6 +24749,7 @@
ActivityManagerService.this.onUserStoppedLocked(userId);
}
mBatteryStatsService.onUserRemoved(userId);
+ mUserController.onUserRemoved(userId);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index eb022b7..66f0592 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -42,6 +42,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.util.StatsLog;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.SomeArgs;
@@ -431,6 +432,12 @@
builder.setType(type);
builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
mMetricsLogger.write(builder);
+ StatsLog.write(
+ StatsLog.APP_START_CANCEL_CHANGED,
+ info.launchedActivity.appInfo.uid,
+ info.launchedActivity.packageName,
+ convertAppStartTransitionType(type),
+ info.launchedActivity.info.name);
}
private void logAppTransitionMultiEvents() {
@@ -450,9 +457,9 @@
builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
info.launchedActivity.launchedFromPackage);
}
- if (info.launchedActivity.info.launchToken != null) {
- builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN,
- info.launchedActivity.info.launchToken);
+ String launchToken = info.launchedActivity.info.launchToken;
+ if (launchToken != null) {
+ builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, launchToken);
info.launchedActivity.info.launchToken = null;
}
builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
@@ -470,9 +477,37 @@
}
builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
mMetricsLogger.write(builder);
+ StatsLog.write(
+ StatsLog.APP_START_CHANGED,
+ info.launchedActivity.appInfo.uid,
+ info.launchedActivity.packageName,
+ convertAppStartTransitionType(type),
+ info.launchedActivity.info.name,
+ info.launchedActivity.launchedFromPackage,
+ isInstantApp,
+ mCurrentTransitionDeviceUptime * 1000,
+ info.reason,
+ mCurrentTransitionDelayMs,
+ info.startingWindowDelayMs,
+ info.bindApplicationDelayMs,
+ info.windowsDrawnDelayMs,
+ launchToken);
}
}
+ private int convertAppStartTransitionType(int tronType) {
+ if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
+ return StatsLog.APP_START_CHANGED__TYPE__COLD;
+ }
+ if (tronType == TYPE_TRANSITION_WARM_LAUNCH) {
+ return StatsLog.APP_START_CHANGED__TYPE__WARM;
+ }
+ if (tronType == TYPE_TRANSITION_HOT_LAUNCH) {
+ return StatsLog.APP_START_CHANGED__TYPE__HOT;
+ }
+ return StatsLog.APP_START_CHANGED__TYPE__APP_START_TRANSITION_TYPE_UNKNOWN;
+ }
+
void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId());
if (info == null) {
@@ -481,14 +516,24 @@
final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
builder.setPackageName(r.packageName);
builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
- builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS,
- SystemClock.uptimeMillis() - mLastTransitionStartTime);
+ long startupTimeMs = SystemClock.uptimeMillis() - mLastTransitionStartTime;
+ builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, startupTimeMs);
builder.setType(restoredFromBundle
? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
: TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
info.currentTransitionProcessRunning ? 1 : 0);
mMetricsLogger.write(builder);
+ StatsLog.write(
+ StatsLog.APP_START_FULLY_DRAWN_CHANGED,
+ info.launchedActivity.appInfo.uid,
+ info.launchedActivity.packageName,
+ restoredFromBundle
+ ? StatsLog.APP_START_FULLY_DRAWN_CHANGED__TYPE__WITH_BUNDLE
+ : StatsLog.APP_START_FULLY_DRAWN_CHANGED__TYPE__WITHOUT_BUNDLE,
+ info.launchedActivity.info.name,
+ info.currentTransitionProcessRunning,
+ startupTimeMs);
}
private int getTransitionType(StackTransitionInfo info) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 8eb5197..b74c8da 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -135,6 +135,7 @@
import android.app.servertransaction.MoveToDisplayItem;
import android.app.servertransaction.MultiWindowModeChangeItem;
import android.app.servertransaction.NewIntentItem;
+import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.PipModeChangeItem;
import android.app.servertransaction.WindowVisibilityItem;
import android.app.servertransaction.ActivityConfigurationChangeItem;
@@ -1607,6 +1608,17 @@
// The activity may be waiting for stop, but that is no longer appropriate for it.
mStackSupervisor.mStoppingActivities.remove(this);
mStackSupervisor.mGoingToSleepActivities.remove(this);
+
+ // If an activity is not in the paused state when becoming visible, cycle to the paused
+ // state.
+ if (state != PAUSED) {
+ // An activity must be in the {@link PAUSING} state for the system to validate
+ // the move to {@link PAUSED}.
+ state = PAUSING;
+ service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+ PauseActivityItem.obtain(finishing, false /* userLeaving */,
+ configChangeFlags, false /* dontReport */));
+ }
} catch (Exception e) {
// Just skip on any failure; we'll make it visible when it next restarts.
Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
@@ -2730,12 +2742,14 @@
}
/**
- * @return true if the activity contains windows that have
- * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the activity has set
- * {@link #mShowWhenLocked}.
+ * @return true if the activity windowing mode is not
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and activity contains
+ * windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the activity
+ * has set {@link #mShowWhenLocked}.
+ * Multi-windowing mode will be exited if true is returned.
*/
boolean canShowWhenLocked() {
- return !inMultiWindowMode() && (mShowWhenLocked
+ return !inPinnedWindowingMode() && (mShowWhenLocked
|| service.mWindowManager.containsShowWhenLockedWindow(appToken));
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 10c801d..a343965 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -144,7 +143,6 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
-import com.android.server.am.EventLogTags;
import com.android.server.wm.ConfigurationContainer;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.StackWindowListener;
@@ -1013,6 +1011,14 @@
return;
}
+ /**
+ * The intent behind moving a primary split screen stack to the back is usually to hide
+ * behind the home stack. Exit split screen in this case.
+ */
+ if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ }
+
getDisplay().positionChildAtBottom(this);
mStackSupervisor.setFocusStackUnchecked(reason, getDisplay().getTopStack());
if (task != null) {
@@ -1811,7 +1817,7 @@
boolean behindFullscreenActivity = !stackShouldBeVisible;
boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
&& (isInStackLocked(starting) == null);
- final boolean isTopFullscreenStack = getDisplay().isTopFullscreenStack(this);
+ final boolean isTopNotPinnedStack = getDisplay().isTopNotPinnedStack(this);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1833,7 +1839,7 @@
// Now check whether it's really visible depending on Keyguard state.
final boolean reallyVisible = checkKeyguardVisibility(r,
- visibleIgnoringKeyguard, isTop && isTopFullscreenStack);
+ visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
if (visibleIgnoringKeyguard) {
behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible,
behindFullscreenActivity, r);
@@ -5046,7 +5052,7 @@
addTask(task, toTop, "createTaskRecord");
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
.isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
- if (!mStackSupervisor.getLaunchingBoundsController()
+ if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.updateOverrideConfiguration(getOverrideBounds());
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 21085fa..b567303 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -300,7 +300,7 @@
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
- private LaunchingBoundsController mLaunchingBoundsController;
+ private LaunchParamsController mLaunchParamsController;
/**
* Maps the task identifier that activities are currently being started in to the userId of the
@@ -593,8 +593,8 @@
mHandler.getLooper());
mKeyguardController = new KeyguardController(mService, this);
- mLaunchingBoundsController = new LaunchingBoundsController();
- mLaunchingBoundsController.registerDefaultPositioners(this);
+ mLaunchParamsController = new LaunchParamsController(mService);
+ mLaunchParamsController.registerDefaultModifiers(this);
}
@@ -2220,8 +2220,8 @@
|| mService.mSupportsFreeformWindowManagement;
}
- LaunchingBoundsController getLaunchingBoundsController() {
- return mLaunchingBoundsController;
+ LaunchParamsController getLaunchParamsController() {
+ return mLaunchParamsController;
}
protected <T extends ActivityStack> T getStack(int stackId) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index abdbfad..3a13155 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -96,7 +96,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.voice.IVoiceInteractionSession;
@@ -109,6 +108,7 @@
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
+import com.android.server.am.LaunchParamsController.LaunchParams;
import com.android.server.pm.InstantAppResolver;
import java.io.PrintWriter;
@@ -144,7 +144,7 @@
private boolean mLaunchTaskBehind;
private int mLaunchFlags;
- private Rect mLaunchBounds = new Rect();
+ private LaunchParams mLaunchParams = new LaunchParams();
private ActivityRecord mNotTop;
private boolean mDoResume;
@@ -318,6 +318,13 @@
boolean mayWait;
/**
+ * Ensure constructed request matches reset instance.
+ */
+ Request() {
+ reset();
+ }
+
+ /**
* Sets values back to the initial state, clearing any held references.
*/
void reset() {
@@ -332,8 +339,8 @@
resultTo = null;
resultWho = null;
requestCode = 0;
- callingPid = 0;
- callingUid = 0;
+ callingPid = DEFAULT_CALLING_PID;
+ callingUid = DEFAULT_CALLING_UID;
callingPackage = null;
realCallingPid = 0;
realCallingUid = 0;
@@ -412,7 +419,7 @@
mLaunchFlags = starter.mLaunchFlags;
mLaunchMode = starter.mLaunchMode;
- mLaunchBounds.set(starter.mLaunchBounds);
+ mLaunchParams.set(starter.mLaunchParams);
mNotTop = starter.mNotTop;
mDoResume = starter.mDoResume;
@@ -1147,6 +1154,18 @@
preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
}
+ // windowing mode and preferred launch display values from {@link LaunchParams} take
+ // priority over those specified in {@link ActivityOptions}.
+ if (!mLaunchParams.isEmpty()) {
+ if (mLaunchParams.hasPreferredDisplay()) {
+ preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
+ }
+
+ if (mLaunchParams.hasWindowingMode()) {
+ preferredWindowingMode = mLaunchParams.mWindowingMode;
+ }
+ }
+
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
@@ -1371,7 +1390,7 @@
mLaunchFlags = 0;
mLaunchMode = INVALID_LAUNCH_MODE;
- mLaunchBounds.setEmpty();
+ mLaunchParams.reset();
mNotTop = null;
mDoResume = false;
@@ -1418,10 +1437,10 @@
mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
- mLaunchBounds.setEmpty();
+ mLaunchParams.reset();
- mSupervisor.getLaunchingBoundsController().calculateBounds(inTask, null /*layout*/, r,
- sourceRecord, options, mLaunchBounds);
+ mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
+ options, mLaunchParams);
mLaunchMode = r.launchMode;
@@ -1931,7 +1950,7 @@
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
mOptions);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
- updateBounds(mStartActivity.getTask(), mLaunchBounds);
+ updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new task " + mStartActivity.getTask());
@@ -2095,7 +2114,7 @@
return START_TASK_TO_FRONT;
}
- if (!mLaunchBounds.isEmpty()) {
+ if (!mLaunchParams.mBounds.isEmpty()) {
// TODO: Shouldn't we already know what stack to use by the time we get here?
ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
if (stack != mInTask.getStack()) {
@@ -2104,7 +2123,7 @@
mTargetStack = mInTask.getStack();
}
- updateBounds(mInTask, mLaunchBounds);
+ updateBounds(mInTask, mLaunchParams.mBounds);
}
mTargetStack.moveTaskToFrontLocked(
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 4582430..1fcaeef 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -35,6 +35,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.util.function.pooled.PooledLambda;
import libcore.util.EmptyArray;
@@ -117,49 +118,45 @@
}
@Override
- public Future<?> scheduleReadProcStateCpuTimes() {
+ public synchronized Future<?> scheduleCpuSyncDueToSettingChange() {
+ return scheduleSyncLocked("setting-change", UPDATE_CPU);
+ }
+
+ @Override
+ public Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
synchronized (mStats) {
- if (!mStats.mPerProcStateCpuTimesAvailable) {
+ if (!mStats.trackPerProcStateCpuTimes()) {
return null;
}
}
synchronized (BatteryExternalStatsWorker.this) {
if (!mExecutorService.isShutdown()) {
- return mExecutorService.submit(mReadProcStateCpuTimesTask);
+ return mExecutorService.submit(PooledLambda.obtainRunnable(
+ BatteryStatsImpl::updateProcStateCpuTimes,
+ mStats, onBattery, onBatteryScreenOff).recycleOnUse());
}
}
return null;
}
@Override
- public Future<?> scheduleCopyFromAllUidsCpuTimes() {
+ public Future<?> scheduleCopyFromAllUidsCpuTimes(
+ boolean onBattery, boolean onBatteryScreenOff) {
synchronized (mStats) {
- if (!mStats.mPerProcStateCpuTimesAvailable) {
+ if (!mStats.trackPerProcStateCpuTimes()) {
return null;
}
}
synchronized (BatteryExternalStatsWorker.this) {
if (!mExecutorService.isShutdown()) {
- return mExecutorService.submit(mCopyFromAllUidsCpuTimesTask);
+ return mExecutorService.submit(PooledLambda.obtainRunnable(
+ BatteryStatsImpl::copyFromAllUidsCpuTimes,
+ mStats, onBattery, onBatteryScreenOff).recycleOnUse());
}
}
return null;
}
- private final Runnable mReadProcStateCpuTimesTask = new Runnable() {
- @Override
- public void run() {
- mStats.updateProcStateCpuTimes();
- }
- };
-
- private final Runnable mCopyFromAllUidsCpuTimesTask = new Runnable() {
- @Override
- public void run() {
- mStats.copyFromAllUidsCpuTimes();
- }
- };
-
public synchronized Future<?> scheduleWrite() {
if (mExecutorService.isShutdown()) {
return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown"));
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 430320a..c9aa9a2 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -185,6 +185,10 @@
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
}
+ public void systemServicesReady() {
+ mStats.systemServicesReady(mContext);
+ }
+
private final class LocalService extends BatteryStatsInternal {
@Override
public String[] getWifiIfaces() {
@@ -514,6 +518,7 @@
}
}
+ @Override
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
enforceCallingPermission();
synchronized (mStats) {
@@ -521,6 +526,16 @@
}
}
+ @Override
+ public void noteLongPartialWakelockStartFromSource(String name, String historyName,
+ WorkSource workSource) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource);
+ }
+ }
+
+ @Override
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
enforceCallingPermission();
synchronized (mStats) {
@@ -528,6 +543,15 @@
}
}
+ @Override
+ public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
+ WorkSource workSource) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource);
+ }
+ }
+
public void noteStartSensor(int uid, int sensor) {
enforceCallingPermission();
synchronized (mStats) {
@@ -1165,6 +1189,7 @@
pw.println(" --write: force write current collected stats to disk.");
pw.println(" --new-daily: immediately create and write new daily stats record.");
pw.println(" --read-daily: read-load last written daily stats.");
+ pw.println(" --settings: dump the settings key/values related to batterystats");
pw.println(" <package.name>: optional name of package to filter output by.");
pw.println(" -h: print this help text.");
pw.println("Battery stats (batterystats) commands:");
@@ -1177,6 +1202,12 @@
pw.println(" pretend-screen-off: pretend the screen is off, even if screen state changes");
}
+ private void dumpSettings(PrintWriter pw) {
+ synchronized (mStats) {
+ mStats.dumpConstantsLocked(pw);
+ }
+ }
+
private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
i++;
if (i >= args.length) {
@@ -1287,6 +1318,9 @@
} else if ("-h".equals(arg)) {
dumpHelp(pw);
return;
+ } else if ("--settings".equals(arg)) {
+ dumpSettings(pw);
+ return;
} else if ("-a".equals(arg)) {
flags |= BatteryStats.DUMP_VERBOSE;
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
new file mode 100644
index 0000000..5632fc0
--- /dev/null
+++ b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Maps global system settings to system properties.
+ * <p>The properties are dynamically updated when settings change.
+ */
+class GlobalSettingsToPropertiesMapper {
+
+ private static final String TAG = "GlobalSettingsToPropertiesMapper";
+
+ private static final String[][] sGlobalSettingsMapping = new String[][] {
+ // List mapping entries in the following format:
+ // {Settings.Global.SETTING_NAME, "system_property_name"},
+ };
+
+
+ private final ContentResolver mContentResolver;
+ private final String[][] mGlobalSettingsMapping;
+
+ @VisibleForTesting
+ GlobalSettingsToPropertiesMapper(ContentResolver contentResolver,
+ String[][] globalSettingsMapping) {
+ mContentResolver = contentResolver;
+ mGlobalSettingsMapping = globalSettingsMapping;
+ }
+
+ void updatePropertiesFromGlobalSettings() {
+ for (String[] entry : mGlobalSettingsMapping) {
+ final String settingName = entry[0];
+ final String propName = entry[1];
+ Uri settingUri = Settings.Global.getUriFor(settingName);
+ Preconditions.checkNotNull(settingUri, "Setting " + settingName + " not found");
+ ContentObserver co = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updatePropertyFromSetting(settingName, propName);
+ }
+ };
+ updatePropertyFromSetting(settingName, propName);
+ mContentResolver.registerContentObserver(settingUri, false, co);
+ }
+ }
+
+ public static void start(ContentResolver contentResolver) {
+ new GlobalSettingsToPropertiesMapper(contentResolver, sGlobalSettingsMapping)
+ .updatePropertiesFromGlobalSettings();
+ }
+
+ private String getGlobalSetting(String name) {
+ return Settings.Global.getString(mContentResolver, name);
+ }
+
+ private void setProperty(String key, String value) {
+ // Check if need to clear the property
+ if (value == null) {
+ // It's impossible to remove system property, therefore we check previous value to
+ // avoid setting an empty string if the property wasn't set.
+ if (TextUtils.isEmpty(systemPropertiesGet(key))) {
+ return;
+ }
+ value = "";
+ }
+ try {
+ systemPropertiesSet(key, value);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Unable to set property " + key + " value '" + value + "'", e);
+ }
+ }
+
+ @VisibleForTesting
+ protected String systemPropertiesGet(String key) {
+ return SystemProperties.get(key);
+ }
+
+ @VisibleForTesting
+ protected void systemPropertiesSet(String key, String value) {
+ SystemProperties.set(key, value);
+ }
+
+ @VisibleForTesting
+ void updatePropertyFromSetting(String settingName, String propName) {
+ String settingValue = getGlobalSetting(settingName);
+ setProperty(propName, settingValue);
+ }
+}
diff --git a/services/core/java/com/android/server/am/LaunchParamsController.java b/services/core/java/com/android/server/am/LaunchParamsController.java
new file mode 100644
index 0000000..7ab7f98
--- /dev/null
+++ b/services/core/java/com/android/server/am/LaunchParamsController.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import android.annotation.IntDef;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.graphics.Rect;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+/**
+ * {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between
+ * registered {@link LaunchParamsModifier}s.
+ */
+class LaunchParamsController {
+ private final ActivityManagerService mService;
+ private final List<LaunchParamsModifier> mModifiers = new ArrayList<>();
+
+ // Temporary {@link LaunchParams} for internal calculations. This is kept separate from
+ // {@code mTmpCurrent} and {@code mTmpResult} to prevent clobbering values.
+ private final LaunchParams mTmpParams = new LaunchParams();
+
+ private final LaunchParams mTmpCurrent = new LaunchParams();
+ private final LaunchParams mTmpResult = new LaunchParams();
+
+ LaunchParamsController(ActivityManagerService service) {
+ mService = service;
+ }
+
+ /**
+ * Creates a {@link LaunchParamsController} with default registered
+ * {@link LaunchParamsModifier}s.
+ */
+ void registerDefaultModifiers(ActivityStackSupervisor supervisor) {
+ // {@link TaskLaunchParamsModifier} handles window layout preferences.
+ registerModifier(new TaskLaunchParamsModifier());
+
+ // {@link ActivityLaunchParamsModifier} is the most specific modifier and thus should be
+ // registered last (applied first) out of the defaults.
+ registerModifier(new ActivityLaunchParamsModifier(supervisor));
+ }
+
+ /**
+ * Returns the {@link LaunchParams} calculated by the registered modifiers
+ * @param task The {@link TaskRecord} currently being positioned.
+ * @param layout The specified {@link WindowLayout}.
+ * @param activity The {@link ActivityRecord} currently being positioned.
+ * @param source The {@link ActivityRecord} from which activity was started from.
+ * @param options The {@link ActivityOptions} specified for the activity.
+ * @param result The resulting params.
+ */
+ void calculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options, LaunchParams result) {
+ result.reset();
+
+ // We start at the last registered {@link LaunchParamsModifier} as this represents
+ // The modifier closest to the product level. Moving back through the list moves closer to
+ // the platform logic.
+ for (int i = mModifiers.size() - 1; i >= 0; --i) {
+ mTmpCurrent.set(result);
+ mTmpResult.reset();
+ final LaunchParamsModifier modifier = mModifiers.get(i);
+
+ switch(modifier.onCalculate(task, layout, activity, source, options, mTmpCurrent,
+ mTmpResult)) {
+ case RESULT_SKIP:
+ // Do not apply any results when we are told to skip
+ continue;
+ case RESULT_DONE:
+ // Set result and return immediately.
+ result.set(mTmpResult);
+ return;
+ case RESULT_CONTINUE:
+ // Set result and continue
+ result.set(mTmpResult);
+ break;
+ }
+ }
+ }
+
+ /**
+ * A convenience method for laying out a task.
+ * @return {@code true} if bounds were set on the task. {@code false} otherwise.
+ */
+ boolean layoutTask(TaskRecord task, WindowLayout layout) {
+ return layoutTask(task, layout, null /*activity*/, null /*source*/, null /*options*/);
+ }
+
+ boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options) {
+ calculate(task, layout, activity, source, options, mTmpParams);
+
+ // No changes, return.
+ if (mTmpParams.isEmpty()) {
+ return false;
+ }
+
+ mService.mWindowManager.deferSurfaceLayout();
+
+ try {
+ if (mTmpParams.hasPreferredDisplay()
+ && mTmpParams.mPreferredDisplayId != task.getStack().getDisplay().mDisplayId) {
+ mService.moveStackToDisplay(task.getStackId(), mTmpParams.mPreferredDisplayId);
+ }
+
+ if (mTmpParams.hasWindowingMode()
+ && mTmpParams.mWindowingMode != task.getStack().getWindowingMode()) {
+ task.getStack().setWindowingMode(mTmpParams.mWindowingMode);
+ }
+
+ if (!mTmpParams.mBounds.isEmpty()) {
+ task.updateOverrideConfiguration(mTmpParams.mBounds);
+ return true;
+ } else {
+ return false;
+ }
+ } finally {
+ mService.mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ /**
+ * Adds a modifier to participate in future bounds calculation. Note that the last registered
+ * {@link LaunchParamsModifier} will be the first to calculate the bounds.
+ */
+ void registerModifier(LaunchParamsModifier modifier) {
+ if (mModifiers.contains(modifier)) {
+ return;
+ }
+
+ mModifiers.add(modifier);
+ }
+
+ /**
+ * A container for holding launch related fields.
+ */
+ static class LaunchParams {
+ /** The bounds within the parent container. */
+ final Rect mBounds = new Rect();
+
+ /** The id of the display the {@link TaskRecord} would prefer to be on. */
+ int mPreferredDisplayId;
+
+ /** The windowing mode to be in. */
+ int mWindowingMode;
+
+ /** Sets values back to default. {@link #isEmpty} will return {@code true} once called. */
+ void reset() {
+ mBounds.setEmpty();
+ mPreferredDisplayId = INVALID_DISPLAY;
+ mWindowingMode = WINDOWING_MODE_UNDEFINED;
+ }
+
+ /** Copies the values set on the passed in {@link LaunchParams}. */
+ void set(LaunchParams params) {
+ mBounds.set(params.mBounds);
+ mPreferredDisplayId = params.mPreferredDisplayId;
+ mWindowingMode = params.mWindowingMode;
+ }
+
+ /** Returns {@code true} if no values have been explicitly set. */
+ boolean isEmpty() {
+ return mBounds.isEmpty() && mPreferredDisplayId == INVALID_DISPLAY
+ && mWindowingMode == WINDOWING_MODE_UNDEFINED;
+ }
+
+ boolean hasWindowingMode() {
+ return mWindowingMode != WINDOWING_MODE_UNDEFINED;
+ }
+
+ boolean hasPreferredDisplay() {
+ return mPreferredDisplayId != INVALID_DISPLAY;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ LaunchParams that = (LaunchParams) o;
+
+ if (mPreferredDisplayId != that.mPreferredDisplayId) return false;
+ if (mWindowingMode != that.mWindowingMode) return false;
+ return mBounds != null ? mBounds.equals(that.mBounds) : that.mBounds == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mBounds != null ? mBounds.hashCode() : 0;
+ result = 31 * result + mPreferredDisplayId;
+ result = 31 * result + mWindowingMode;
+ return result;
+ }
+ }
+
+ /**
+ * An interface implemented by those wanting to participate in bounds calculation.
+ */
+ interface LaunchParamsModifier {
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
+ @interface Result {}
+
+ // Returned when the modifier does not want to influence the bounds calculation
+ int RESULT_SKIP = 0;
+ // Returned when the modifier has changed the bounds and would like its results to be the
+ // final bounds applied.
+ int RESULT_DONE = 1;
+ // Returned when the modifier has changed the bounds but is okay with other modifiers
+ // influencing the bounds.
+ int RESULT_CONTINUE = 2;
+
+ /**
+ * Called when asked to calculate {@link LaunchParams}.
+ * @param task The {@link TaskRecord} currently being positioned.
+ * @param layout The specified {@link WindowLayout}.
+ * @param activity The {@link ActivityRecord} currently being positioned.
+ * @param source The {@link ActivityRecord} activity was started from.
+ * @param options The {@link ActivityOptions} specified for the activity.
+ * @param currentParams The current {@link LaunchParams}. This can differ from the initial
+ * params as it represents the modified params up to this point.
+ * @param outParams The resulting {@link LaunchParams} after all calculations.
+ * @return A {@link Result} representing the result of the
+ * {@link LaunchParams} calculation.
+ */
+ @Result
+ int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
+ LaunchParams outParams);
+ }
+}
diff --git a/services/core/java/com/android/server/am/LaunchingBoundsController.java b/services/core/java/com/android/server/am/LaunchingBoundsController.java
deleted file mode 100644
index 5aa7f58..0000000
--- a/services/core/java/com/android/server/am/LaunchingBoundsController.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import android.annotation.IntDef;
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.graphics.Rect;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_CONTINUE;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_DONE;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_SKIP;
-
-/**
- * {@link LaunchingBoundsController} calculates the launch bounds by coordinating between registered
- * {@link LaunchingBoundsPositioner}.
- */
-class LaunchingBoundsController {
- private final List<LaunchingBoundsPositioner> mPositioners = new ArrayList<>();
-
- // Temporary {@link Rect} for calculations. This is kept separate from {@code mTmpCurrent} and
- // {@code mTmpResult} to prevent clobbering values.
- private final Rect mTmpRect = new Rect();
-
- private final Rect mTmpCurrent = new Rect();
- private final Rect mTmpResult = new Rect();
-
- /**
- * Creates a {@link LaunchingBoundsController} with default registered
- * {@link LaunchingBoundsPositioner}s.
- */
- void registerDefaultPositioners(ActivityStackSupervisor supervisor) {
- // {@link LaunchingTaskPositioner} handles window layout preferences.
- registerPositioner(new LaunchingTaskPositioner());
-
- // {@link LaunchingActivityPositioner} is the most specific positioner and thus should be
- // registered last (applied first) out of the defaults.
- registerPositioner(new LaunchingActivityPositioner(supervisor));
- }
-
- /**
- * Returns the position calculated by the registered positioners
- * @param task The {@link TaskRecord} currently being positioned.
- * @param layout The specified {@link WindowLayout}.
- * @param activity The {@link ActivityRecord} currently being positioned.
- * @param source The {@link ActivityRecord} from which activity was started from.
- * @param options The {@link ActivityOptions} specified for the activity.
- * @param result The resulting bounds. If no bounds are set, {@link Rect#isEmpty()} will be
- * {@code true}.
- */
- void calculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, Rect result) {
- result.setEmpty();
-
- // We start at the last registered {@link LaunchingBoundsPositioner} as this represents
- // The positioner closest to the product level. Moving back through the list moves closer to
- // the platform logic.
- for (int i = mPositioners.size() - 1; i >= 0; --i) {
- mTmpResult.setEmpty();
- mTmpCurrent.set(result);
- final LaunchingBoundsPositioner positioner = mPositioners.get(i);
-
- switch(positioner.onCalculateBounds(task, layout, activity, source, options,
- mTmpCurrent, mTmpResult)) {
- case RESULT_SKIP:
- // Do not apply any results when we are told to skip
- continue;
- case RESULT_DONE:
- // Set result and return immediately.
- result.set(mTmpResult);
- return;
- case RESULT_CONTINUE:
- // Set result and continue
- result.set(mTmpResult);
- break;
- }
- }
- }
-
- /**
- * A convenience method for laying out a task.
- * @return {@code true} if bounds were set on the task. {@code false} otherwise.
- */
- boolean layoutTask(TaskRecord task, WindowLayout layout) {
- return layoutTask(task, layout, null /*activity*/, null /*source*/, null /*options*/);
- }
-
- boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options) {
- calculateBounds(task, layout, activity, source, options, mTmpRect);
-
- if (mTmpRect.isEmpty()) {
- return false;
- }
-
- task.updateOverrideConfiguration(mTmpRect);
-
- return true;
- }
-
- /**
- * Adds a positioner to participate in future bounds calculation. Note that the last registered
- * {@link LaunchingBoundsPositioner} will be the first to calculate the bounds.
- */
- void registerPositioner(LaunchingBoundsPositioner positioner) {
- if (mPositioners.contains(positioner)) {
- return;
- }
-
- mPositioners.add(positioner);
- }
-
- /**
- * An interface implemented by those wanting to participate in bounds calculation.
- */
- interface LaunchingBoundsPositioner {
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
- @interface Result {}
-
- // Returned when the positioner does not want to influence the bounds calculation
- int RESULT_SKIP = 0;
- // Returned when the positioner has changed the bounds and would like its results to be the
- // final bounds applied.
- int RESULT_DONE = 1;
- // Returned when the positioner has changed the bounds but is okay with other positioners
- // influencing the bounds.
- int RESULT_CONTINUE = 2;
-
- /**
- * Called when asked to calculate bounds.
- * @param task The {@link TaskRecord} currently being positioned.
- * @param layout The specified {@link WindowLayout}.
- * @param activity The {@link ActivityRecord} currently being positioned.
- * @param source The {@link ActivityRecord} activity was started from.
- * @param options The {@link ActivityOptions} specified for the activity.
- * @param current The current bounds. This can differ from the initial bounds as it
- * represents the modified bounds up to this point.
- * @param result The {@link Rect} which the positioner should return its modified bounds.
- * Any merging of the current bounds should be already applied to this
- * value as well before returning.
- * @return A {@link Result} representing the result of the bounds calculation.
- */
- @Result
- int onCalculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, Rect current, Rect result);
- }
-}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index ab5d64c..77f5c16 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -358,12 +358,12 @@
case ActivityManager.PROCESS_STATE_TOP:
procState = "TOP ";
break;
- case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- procState = "BFGS";
- break;
case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
procState = "FGS ";
break;
+ case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+ procState = "BFGS";
+ break;
case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
procState = "IMPF";
break;
@@ -432,13 +432,13 @@
public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
// The maximum amount of time we want to go between PSS collections.
- public static final int PSS_MAX_INTERVAL = 30*60*1000;
+ public static final int PSS_MAX_INTERVAL = 40*60*1000;
// The minimum amount of time between successive PSS requests for *all* processes.
- public static final int PSS_ALL_INTERVAL = 10*60*1000;
+ public static final int PSS_ALL_INTERVAL = 20*60*1000;
- // The minimum amount of time between successive PSS requests for a process.
- private static final int PSS_SHORT_INTERVAL = 2*60*1000;
+ // The amount of time until PSS when a persistent process first appears.
+ private static final int PSS_FIRST_PERSISTENT_INTERVAL = 30*1000;
// The amount of time until PSS when a process first becomes top.
private static final int PSS_FIRST_TOP_INTERVAL = 10*1000;
@@ -449,6 +449,9 @@
// The amount of time until PSS when a process first becomes cached.
private static final int PSS_FIRST_CACHED_INTERVAL = 30*1000;
+ // The amount of time until PSS when the top process stays in the same state.
+ private static final int PSS_SAME_TOP_INTERVAL = 5*60*1000;
+
// The amount of time until PSS when an important process stays in the same state.
private static final int PSS_SAME_IMPORTANT_INTERVAL = 15*60*1000;
@@ -458,6 +461,18 @@
// The amount of time until PSS when a cached process stays in the same state.
private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000;
+ // The amount of time until PSS when a persistent process first appears.
+ private static final int PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL = 1*60*1000;
+
+ // The amount of time until PSS when a process first becomes top.
+ private static final int PSS_FIRST_ASLEEP_TOP_INTERVAL = 20*1000;
+
+ // The amount of time until PSS when a process first goes into the background.
+ private static final int PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL = 30*1000;
+
+ // The amount of time until PSS when a process first becomes cached.
+ private static final int PSS_FIRST_ASLEEP_CACHED_INTERVAL = 1*60*1000;
+
// The minimum time interval after a state change it is safe to collect PSS.
public static final int PSS_TEST_MIN_TIME_FROM_STATE_CHANGE = 10*1000;
@@ -483,8 +498,8 @@
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_TOP
- PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -502,11 +517,11 @@
};
private static final long[] sFirstAwakePssTimes = new long[] {
- PSS_SHORT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_SHORT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
+ PSS_FIRST_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
+ PSS_FIRST_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
PSS_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -526,9 +541,54 @@
private static final long[] sSameAwakePssTimes = new long[] {
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_SHORT_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ PSS_SAME_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
+ PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
+ PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
+ PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ };
+
+ private static final long[] sFirstAsleepPssTimes = new long[] {
+ PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
+ PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
+ PSS_FIRST_ASLEEP_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ };
+
+ private static final long[] sSameAsleepPssTimes = new long[] {
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
+ PSS_SAME_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -549,8 +609,8 @@
PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -571,8 +631,8 @@
PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
@@ -604,8 +664,8 @@
? sTestFirstPssTimes
: sTestSamePssTimes)
: (first
- ? sFirstAwakePssTimes
- : sSameAwakePssTimes);
+ ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
+ : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
return now + table[procState];
}
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
similarity index 93%
rename from services/core/java/com/android/server/am/LaunchingTaskPositioner.java
rename to services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
index d89568e..92f1cc3 100644
--- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
+++ b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
@@ -21,26 +21,27 @@
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo;
-import android.graphics.Point;
import android.graphics.Rect;
import android.util.Slog;
import android.view.Gravity;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.am.LaunchParamsController.LaunchParams;
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
import java.util.ArrayList;
/**
* Determines where a launching task should be positioned and sized on the display.
*
- * The positioner is fairly simple. For the new task it tries default position based on the gravity
+ * The modifier is fairly simple. For the new task it tries default position based on the gravity
* and compares corners of the task with corners of existing tasks. If some two pairs of corners are
* sufficiently close enough, it shifts the bounds of the new task and tries again. When it exhausts
* all possible shifts, it gives up and puts the task in the original position.
*
* Note that the only gravities of concern are the corners and the center.
*/
-class LaunchingTaskPositioner implements LaunchingBoundsController.LaunchingBoundsPositioner {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "LaunchingTaskPositioner" : TAG_AM;
+class TaskLaunchParamsModifier implements LaunchParamsModifier {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_AM;
// Determines how close window frames/corners have to be to call them colliding.
private static final int BOUNDS_CONFLICT_MIN_DISTANCE = 4;
@@ -70,17 +71,15 @@
private final Rect mTmpProposal = new Rect();
private final Rect mTmpOriginal = new Rect();
- private final Point mDisplaySize = new Point();
-
/**
* Tries to set task's bound in a way that it won't collide with any other task. By colliding
* we mean that two tasks have left-top corner very close to each other, so one might get
* obfuscated by the other one.
*/
@Override
- public int onCalculateBounds(TaskRecord task, ActivityInfo.WindowLayout layout,
- ActivityRecord activity, ActivityRecord source,
- ActivityOptions options, Rect current, Rect result) {
+ public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
+ ActivityRecord activity, ActivityRecord source, ActivityOptions options,
+ LaunchParams currentParams, LaunchParams outParams) {
// We can only apply positioning if we're in a freeform stack.
if (task == null || task.getStack() == null || !task.inFreeformWindowingMode()) {
return RESULT_SKIP;
@@ -90,9 +89,11 @@
mAvailableRect.set(task.getParent().getBounds());
+ final Rect resultBounds = outParams.mBounds;
+
if (layout == null) {
positionCenter(tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
- getFreeformHeight(mAvailableRect), result);
+ getFreeformHeight(mAvailableRect), resultBounds);
return RESULT_CONTINUE;
}
@@ -102,22 +103,22 @@
int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (verticalGravity == Gravity.TOP) {
if (horizontalGravity == Gravity.RIGHT) {
- positionTopRight(tasks, mAvailableRect, width, height, result);
+ positionTopRight(tasks, mAvailableRect, width, height, resultBounds);
} else {
- positionTopLeft(tasks, mAvailableRect, width, height, result);
+ positionTopLeft(tasks, mAvailableRect, width, height, resultBounds);
}
} else if (verticalGravity == Gravity.BOTTOM) {
if (horizontalGravity == Gravity.RIGHT) {
- positionBottomRight(tasks, mAvailableRect, width, height, result);
+ positionBottomRight(tasks, mAvailableRect, width, height, resultBounds);
} else {
- positionBottomLeft(tasks, mAvailableRect, width, height, result);
+ positionBottomLeft(tasks, mAvailableRect, width, height, resultBounds);
}
} else {
// Some fancy gravity setting that we don't support yet. We just put the activity in the
// center.
Slog.w(TAG, "Received unsupported gravity: " + layout.gravity
+ ", positioning in the center instead.");
- positionCenter(tasks, mAvailableRect, width, height, result);
+ positionCenter(tasks, mAvailableRect, width, height, resultBounds);
}
return RESULT_CONTINUE;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 4aef95d..b131e86 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -714,7 +714,7 @@
} else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Rect bounds = getLaunchBounds();
if (bounds == null) {
- mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null);
+ mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
bounds = configBounds;
}
kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
@@ -1838,7 +1838,7 @@
if (mLastNonFullscreenBounds != null) {
updateOverrideConfiguration(mLastNonFullscreenBounds);
} else {
- mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null);
+ mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
}
} else {
updateOverrideConfiguration(inStack.getOverrideBounds());
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 34621e0..c4fdffa 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1762,6 +1762,20 @@
}
}
+ void onUserRemoved(int userId) {
+ synchronized (mLock) {
+ int size = mUserProfileGroupIds.size();
+ for (int i = size - 1; i >= 0; i--) {
+ if (mUserProfileGroupIds.keyAt(i) == userId
+ || mUserProfileGroupIds.valueAt(i) == userId) {
+ mUserProfileGroupIds.removeAt(i);
+
+ }
+ }
+ mCurrentProfileIds = ArrayUtils.removeInt(mCurrentProfileIds, userId);
+ }
+ }
+
/**
* Returns whether the given user requires credential entry at this time. This is used to
* intercept activity launches for work apps when the Work Challenge is present.
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index c298fe70..48f0d5a 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -25,6 +25,7 @@
import android.os.IBinder;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler;
import java.io.PrintWriter;
@@ -300,16 +301,19 @@
}
/**
- * Called synchronized on MediaFocusControl.mAudioFocusLock
+ * Handle the loss of focus resulting from a given focus gain.
+ * @param focusGain the focus gain from which the loss of focus is resulting
+ * @param frWinner the new focus owner
+ * @return true if the focus loss is definitive, false otherwise.
*/
- void handleExternalFocusGain(int focusGain, final FocusRequester fr) {
- int focusLoss = focusLossForGainRequest(focusGain);
- handleFocusLoss(focusLoss, fr);
+ @GuardedBy("MediaFocusControl.mAudioFocusLock")
+ boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner) {
+ final int focusLoss = focusLossForGainRequest(focusGain);
+ handleFocusLoss(focusLoss, frWinner);
+ return (focusLoss == AudioManager.AUDIOFOCUS_LOSS);
}
- /**
- * Called synchronized on MediaFocusControl.mAudioFocusLock
- */
+ @GuardedBy("MediaFocusControl.mAudioFocusLock")
void handleFocusGain(int focusGain) {
try {
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
@@ -331,19 +335,15 @@
}
}
- /**
- * Called synchronized on MediaFocusControl.mAudioFocusLock
- */
+ @GuardedBy("MediaFocusControl.mAudioFocusLock")
void handleFocusGainFromRequest(int focusRequestResult) {
if (focusRequestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mFocusController.unduckPlayers(this);
}
}
- /**
- * Called synchronized on MediaFocusControl.mAudioFocusLock
- */
- void handleFocusLoss(int focusLoss, @Nullable final FocusRequester fr) {
+ @GuardedBy("MediaFocusControl.mAudioFocusLock")
+ void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner) {
try {
if (focusLoss != mFocusLossReceived) {
mFocusLossReceived = focusLoss;
@@ -371,9 +371,9 @@
boolean handled = false;
if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
&& MediaFocusControl.ENFORCE_DUCKING
- && fr != null) {
+ && frWinner != null) {
// candidate for enforcement by the framework
- if (fr.mCallingUid != this.mCallingUid) {
+ if (frWinner.mCallingUid != this.mCallingUid) {
if ((mGrantFlags
& AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
// the focus loser declared it would pause instead of duck, let it
@@ -386,7 +386,7 @@
handled = false;
Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK");
} else {
- handled = mFocusController.duckPlayers(fr, this);
+ handled = mFocusController.duckPlayers(frWinner, this);
}
} // 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 c5f563c7..de58b59 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -32,11 +32,15 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
@@ -146,9 +150,7 @@
}
}
- /**
- * Called synchronized on mAudioFocusLock
- */
+ @GuardedBy("mAudioFocusLock")
private void notifyTopOfAudioFocusStack() {
// notify the top of the stack it gained focus
if (!mFocusStack.empty()) {
@@ -160,14 +162,24 @@
/**
* Focus is requested, propagate the associated loss throughout the stack.
+ * Will also remove entries in the stack that have just received a definitive loss of focus.
* @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) {
+ 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
- Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
- while(stackIterator.hasNext()) {
- stackIterator.next().handleExternalFocusGain(focusGain, fr);
+ for (FocusRequester focusLoser : mFocusStack) {
+ final boolean isDefinitiveLoss =
+ focusLoser.handleFocusLossFromGain(focusGain, fr);
+ if (isDefinitiveLoss) {
+ clientsToRemove.add(focusLoser.getClientId());
+ }
+ }
+ for (String clientToRemove : clientsToRemove) {
+ removeFocusStackEntry(clientToRemove, false /*signal*/,
+ true /*notifyFocusFollowers*/);
}
}
@@ -198,13 +210,12 @@
}
/**
- * Helper function:
- * Called synchronized on mAudioFocusLock
* Remove a focus listener from the focus stack.
* @param clientToRemove the focus listener
* @param signal if true and the listener was at the top of the focus stack, i.e. it was holding
* focus, notify the next item in the stack it gained focus.
*/
+ @GuardedBy("mAudioFocusLock")
private void removeFocusStackEntry(String clientToRemove, boolean signal,
boolean notifyFocusFollowers) {
// is the current top of the focus stack abandoning focus? (because of request, not death)
@@ -242,10 +253,9 @@
}
/**
- * Helper function:
- * Called synchronized on mAudioFocusLock
* Remove focus listeners from the focus stack for a particular client when it has died.
*/
+ @GuardedBy("mAudioFocusLock")
private void removeFocusStackEntryOnDeath(IBinder cb) {
// is the owner of the audio focus part of the client to remove?
boolean isTopOfStackForClientToRemove = !mFocusStack.isEmpty() &&
@@ -271,10 +281,10 @@
/**
* Helper function for external focus policy:
- * Called synchronized on mAudioFocusLock
* Remove focus listeners from the list of potential focus owners for a particular client when
* it has died.
*/
+ @GuardedBy("mAudioFocusLock")
private void removeFocusEntryForExtPolicy(IBinder cb) {
if (mFocusOwnersForFocusPolicy.isEmpty()) {
return;
@@ -324,6 +334,7 @@
* @return {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED} or
* {@link AudioManager#AUDIOFOCUS_REQUEST_DELAYED}
*/
+ @GuardedBy("mAudioFocusLock")
private int pushBelowLockedFocusOwners(FocusRequester nfr) {
int lastLockedFocusOwnerIndex = mFocusStack.size();
for (int index = mFocusStack.size()-1; index >= 0; index--) {
diff --git a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
index ef51665..7d3b670 100644
--- a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
@@ -94,7 +94,7 @@
}
synchronized (mLock) {
if (mHal2.hasModule(moduleId)) {
- return mHal2.openSession(moduleId, callback);
+ return mHal2.openSession(moduleId, bandConfig, withAudio, callback);
} else {
return mHal1.openTuner(moduleId, bandConfig, withAudio, callback);
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index cce534d..e5090ed 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -263,19 +263,31 @@
}
@Override
- public boolean isAnalogForced() {
- synchronized (mLock) {
- checkNotClosedLocked();
- return nativeIsAnalogForced(mNativeContext);
- }
+ public boolean isConfigFlagSupported(int flag) {
+ return flag == RadioManager.CONFIG_FORCE_ANALOG;
}
@Override
- public void setAnalogForced(boolean isForced) {
- synchronized (mLock) {
- checkNotClosedLocked();
- nativeSetAnalogForced(mNativeContext, isForced);
+ public boolean isConfigFlagSet(int flag) {
+ if (flag == RadioManager.CONFIG_FORCE_ANALOG) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return nativeIsAnalogForced(mNativeContext);
+ }
}
+ throw new UnsupportedOperationException("Not supported by HAL 1.x");
+ }
+
+ @Override
+ public void setConfigFlag(int flag, boolean value) {
+ if (flag == RadioManager.CONFIG_FORCE_ANALOG) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ nativeSetAnalogForced(mNativeContext, value);
+ return;
+ }
+ }
+ throw new UnsupportedOperationException("Not supported by HAL 1.x");
}
@Override
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 413a27c..9158ff0 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -17,6 +17,7 @@
package com.android.server.broadcastradio.hal2;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.hardware.radio.ITuner;
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
@@ -80,14 +81,21 @@
return mModules.containsKey(id);
}
- public ITuner openSession(int moduleId, @NonNull ITunerCallback callback) {
+ public ITuner openSession(int moduleId, @Nullable RadioManager.BandConfig legacyConfig,
+ boolean withAudio, @NonNull ITunerCallback callback) {
Objects.requireNonNull(callback);
+ if (!withAudio) {
+ throw new IllegalArgumentException("Non-audio sessions not supported with HAL 2.x");
+ }
+
RadioModule module = mModules.get(moduleId);
if (module == null) {
throw new IllegalArgumentException("Invalid module ID");
}
- return module.openSession(callback);
+ TunerSession session = module.openSession(callback);
+ session.setConfiguration(legacyConfig);
+ return session;
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
index 434e262..2c129bb 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
@@ -186,7 +186,7 @@
false, // isCaptureSupported
amfmConfigToBands(amfmConfig),
- true, // isBgScanSupported is deprecated
+ false, // isBgScanSupported is deprecated
supportedProgramTypes,
supportedIdentifierTypes,
vendorInfoFromHal(prop.vendorInfo));
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 8a7ac73..45b2190 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -63,7 +63,7 @@
}
}
- public @NonNull ITuner openSession(@NonNull android.hardware.radio.ITunerCallback userCb) {
+ public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb) {
TunerCallback cb = new TunerCallback(Objects.requireNonNull(userCb));
Mutable<ITunerSession> hwSession = new Mutable<>();
MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
@@ -81,25 +81,6 @@
Convert.throwOnError("openSession", halResult.value);
Objects.requireNonNull(hwSession.value);
- TunerSession session = new TunerSession(hwSession.value, cb);
-
- // send out legacy callback about band configuration
- RadioManager.BandDescriptor[] bands = mProperties.getBands();
- if (bands != null && bands.length > 0) {
- RadioManager.BandDescriptor descr = bands[0]; // just pick first
- Mutable<RadioManager.BandConfig> config = new Mutable<>();
- if (descr instanceof RadioManager.FmBandDescriptor) {
- config.value = new RadioManager.FmBandConfig((RadioManager.FmBandDescriptor)descr);
- } else if (descr instanceof RadioManager.AmBandDescriptor) {
- config.value = new RadioManager.AmBandConfig((RadioManager.AmBandDescriptor)descr);
- } else {
- Slog.w(TAG, "Descriptor is neither AM nor FM");
- }
- if (config.value != null) {
- TunerCallback.dispatch(() -> userCb.onConfigurationChanged(config.value));
- }
- }
-
- return session;
+ return new TunerSession(hwSession.value, cb);
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
index 5ee6a4c..c9084ee 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
@@ -31,14 +31,14 @@
class TunerCallback extends ITunerCallback.Stub {
private static final String TAG = "BcRadio2Srv.cb";
- final android.hardware.radio.ITunerCallback mCb;
+ final android.hardware.radio.ITunerCallback mClientCb;
interface RunnableThrowingRemoteException {
void run() throws RemoteException;
}
TunerCallback(@NonNull android.hardware.radio.ITunerCallback clientCallback) {
- mCb = Objects.requireNonNull(clientCallback);
+ mClientCb = Objects.requireNonNull(clientCallback);
}
static void dispatch(RunnableThrowingRemoteException func) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index e8faf3d..8ed646a 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -18,10 +18,16 @@
import android.annotation.NonNull;
import android.graphics.Bitmap;
+import android.hardware.broadcastradio.V2_0.ConfigFlag;
import android.hardware.broadcastradio.V2_0.ITunerSession;
+import android.hardware.broadcastradio.V2_0.Result;
import android.hardware.radio.ITuner;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
+import android.media.AudioSystem;
+import android.os.RemoteException;
+import android.util.MutableBoolean;
+import android.util.MutableInt;
import android.util.Slog;
import java.util.List;
@@ -30,16 +36,23 @@
class TunerSession extends ITuner.Stub {
private static final String TAG = "BcRadio2Srv.session";
+ private static final String kAudioDeviceName = "Radio tuner source";
private final Object mLock = new Object();
private final ITunerSession mHwSession;
private final TunerCallback mCallback;
private boolean mIsClosed = false;
+ private boolean mIsAudioConnected = false;
+ private boolean mIsMuted = false;
+
+ // necessary only for older APIs compatibility
+ private RadioManager.BandConfig mDummyConfig = null;
TunerSession(@NonNull ITunerSession hwSession, @NonNull TunerCallback callback) {
mHwSession = Objects.requireNonNull(hwSession);
mCallback = Objects.requireNonNull(callback);
+ notifyAudioServiceLocked(true);
}
@Override
@@ -47,6 +60,7 @@
synchronized (mLock) {
if (mIsClosed) return;
mIsClosed = true;
+ notifyAudioServiceLocked(false);
}
}
@@ -61,77 +75,193 @@
}
}
+ private void notifyAudioServiceLocked(boolean connected) {
+ if (mIsAudioConnected == connected) return;
+
+ Slog.d(TAG, "Notifying AudioService about new state: " + connected);
+ int ret = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER,
+ connected ? AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
+ null, kAudioDeviceName);
+
+ if (ret == AudioSystem.AUDIO_STATUS_OK) {
+ mIsAudioConnected = connected;
+ } else {
+ Slog.e(TAG, "Failed to notify AudioService about new state: " + connected);
+ }
+ }
+
@Override
- public void setConfiguration(RadioManager.BandConfig config) {}
+ public void setConfiguration(RadioManager.BandConfig config) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ mDummyConfig = Objects.requireNonNull(config);
+ Slog.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL 2.x");
+ TunerCallback.dispatch(() -> mCallback.mClientCb.onConfigurationChanged(config));
+ }
+ }
@Override
public RadioManager.BandConfig getConfiguration() {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return mDummyConfig;
+ }
}
@Override
- public void setMuted(boolean mute) {}
+ public void setMuted(boolean mute) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ if (mIsMuted == mute) return;
+ mIsMuted = mute;
+ notifyAudioServiceLocked(!mute);
+ }
+ }
@Override
public boolean isMuted() {
- return false;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return mIsMuted;
+ }
}
@Override
- public void step(boolean directionDown, boolean skipSubChannel) {}
+ public void step(boolean directionDown, boolean skipSubChannel) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ }
+ }
@Override
- public void scan(boolean directionDown, boolean skipSubChannel) {}
+ public void scan(boolean directionDown, boolean skipSubChannel) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ }
+ }
@Override
- public void tune(ProgramSelector selector) {}
+ public void tune(ProgramSelector selector) {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ }
+ }
@Override
- public void cancel() {}
+ public void cancel() {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ }
+ }
@Override
- public void cancelAnnouncement() {}
+ public void cancelAnnouncement() {
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ }
+ }
@Override
public RadioManager.ProgramInfo getProgramInformation() {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return null;
+ }
}
@Override
public Bitmap getImage(int id) {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return null;
+ }
}
@Override
public boolean startBackgroundScan() {
+ Slog.i(TAG, "Explicit background scan trigger is not supported with HAL 2.x");
return false;
}
@Override
public List<RadioManager.ProgramInfo> getProgramList(Map vendorFilter) {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return null;
+ }
}
@Override
- public boolean isAnalogForced() {
- return false;
+ public boolean isConfigFlagSupported(int flag) {
+ try {
+ isConfigFlagSet(flag);
+ return true;
+ } catch (IllegalStateException ex) {
+ return true;
+ } catch (UnsupportedOperationException ex) {
+ return false;
+ }
}
@Override
- public void setAnalogForced(boolean isForced) {}
+ public boolean isConfigFlagSet(int flag) {
+ Slog.v(TAG, "isConfigFlagSet " + ConfigFlag.toString(flag));
+ synchronized (mLock) {
+ checkNotClosedLocked();
+
+ MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
+ MutableBoolean flagState = new MutableBoolean(false);
+ try {
+ mHwSession.getConfigFlag(flag, (int result, boolean value) -> {
+ halResult.value = result;
+ flagState.value = value;
+ });
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Failed to check flag " + ConfigFlag.toString(flag), ex);
+ }
+ Convert.throwOnError("isConfigFlagSet", halResult.value);
+
+ return flagState.value;
+ }
+ }
+
+ @Override
+ public void setConfigFlag(int flag, boolean value) {
+ Slog.v(TAG, "setConfigFlag " + ConfigFlag.toString(flag) + " = " + value);
+ synchronized (mLock) {
+ checkNotClosedLocked();
+
+ int halResult;
+ try {
+ halResult = mHwSession.setConfigFlag(flag, value);
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Failed to set flag " + ConfigFlag.toString(flag), ex);
+ }
+ Convert.throwOnError("setConfigFlag", halResult);
+ }
+ }
@Override
public Map setParameters(Map parameters) {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return null;
+ }
}
@Override
public Map getParameters(List<String> keys) {
- return null;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return null;
+ }
}
@Override
public boolean isAntennaConnected() {
- return true;
+ synchronized (mLock) {
+ checkNotClosedLocked();
+ return true;
+ }
}
}
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
new file mode 100644
index 0000000..a4170ce
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -0,0 +1,226 @@
+/*
+ * 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.connectivity;
+
+import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
+import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
+import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
+import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkUtils;
+import android.os.Binder;
+import android.os.INetworkManagementService;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.server.connectivity.MockableSystemProperties;
+
+import java.net.InetAddress;
+import java.util.Collection;
+
+
+/**
+ * Encapsulate the management of DNS settings for networks.
+ *
+ * This class it NOT designed for concurrent access. Furthermore, all non-static
+ * methods MUST be called from ConnectivityService's thread.
+ *
+ * @hide
+ */
+public class DnsManager {
+ private static final String TAG = DnsManager.class.getSimpleName();
+
+ /* Defaults for resolver parameters. */
+ private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
+ private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
+ private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
+ private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
+
+ private final Context mContext;
+ private final ContentResolver mContentResolver;
+ private final INetworkManagementService mNMS;
+ private final MockableSystemProperties mSystemProperties;
+
+ private int mNumDnsEntries;
+ private int mSampleValidity;
+ private int mSuccessThreshold;
+ private int mMinSamples;
+ private int mMaxSamples;
+ private String mPrivateDnsMode;
+ private String mPrivateDnsSpecifier;
+
+ public DnsManager(Context ctx, INetworkManagementService nms, MockableSystemProperties sp) {
+ mContext = ctx;
+ mContentResolver = mContext.getContentResolver();
+ mNMS = nms;
+ mSystemProperties = sp;
+
+ // TODO: Create and register ContentObservers to track every setting
+ // used herein, posting messages to respond to changes.
+ }
+
+ public boolean isPrivateDnsInStrictMode() {
+ return !TextUtils.isEmpty(mPrivateDnsMode) &&
+ mPrivateDnsMode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) &&
+ !TextUtils.isEmpty(mPrivateDnsSpecifier);
+ }
+
+ public void setDnsConfigurationForNetwork(
+ int netId, Collection<InetAddress> servers, String domains, boolean isDefaultNetwork) {
+ updateParametersSettings();
+ updatePrivateDnsSettings();
+
+ final String[] serverStrs = NetworkUtils.makeStrings(servers);
+ final String[] domainStrs = (domains == null) ? new String[0] : domains.split(" ");
+ final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+ final boolean useTls = shouldUseTls(mPrivateDnsMode);
+ // TODO: Populate tlsHostname once it's decided how the hostname's IP
+ // addresses will be resolved:
+ //
+ // [1] network-provided DNS servers are included here with the
+ // hostname and netd will use the network-provided servers to
+ // resolve the hostname and fix up its internal structures, or
+ //
+ // [2] network-provided DNS servers are included here without the
+ // hostname, the ConnectivityService layer resolves the given
+ // hostname, and then reconfigures netd with this information.
+ //
+ // In practice, there will always be a need for ConnectivityService or
+ // the captive portal app to use the network-provided services to make
+ // some queries. This argues in favor of [1], in concert with another
+ // mechanism, perhaps setting a high bit in the netid, to indicate
+ // via existing DNS APIs which set of servers (network-provided or
+ // non-network-provided private DNS) should be queried.
+ final String tlsHostname = "";
+ try {
+ mNMS.setDnsConfigurationForNetwork(
+ netId, serverStrs, domainStrs, params, useTls, tlsHostname);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting DNS configuration: " + e);
+ return;
+ }
+
+ // TODO: netd should listen on [::1]:53 and proxy queries to the current
+ // default network, and we should just set net.dns1 to ::1, not least
+ // because applications attempting to use net.dns resolvers will bypass
+ // the privacy protections of things like DNS-over-TLS.
+ if (isDefaultNetwork) setDefaultDnsSystemProperties(servers);
+ flushVmDnsCache();
+ }
+
+ public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
+ int last = 0;
+ for (InetAddress dns : dnses) {
+ ++last;
+ setNetDnsProperty(last, dns.getHostAddress());
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ setNetDnsProperty(i, "");
+ }
+ mNumDnsEntries = last;
+ }
+
+ private void flushVmDnsCache() {
+ /*
+ * Tell the VMs to toss their DNS caches
+ */
+ final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ /*
+ * Connectivity events can happen before boot has completed ...
+ */
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void updatePrivateDnsSettings() {
+ mPrivateDnsMode = getStringSetting(PRIVATE_DNS_MODE);
+ mPrivateDnsSpecifier = getStringSetting(PRIVATE_DNS_SPECIFIER);
+ }
+
+ private void updateParametersSettings() {
+ mSampleValidity = getIntSetting(
+ DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ if (mSampleValidity < 0 || mSampleValidity > 65535) {
+ Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
+ }
+
+ mSuccessThreshold = getIntSetting(
+ DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
+ Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
+ }
+
+ mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
+ mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
+ if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
+ Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
+ "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
+ DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
+ mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
+ mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
+ }
+ }
+
+ private String getStringSetting(String which) {
+ return Settings.Global.getString(mContentResolver, which);
+ }
+
+ private int getIntSetting(String which, int dflt) {
+ return Settings.Global.getInt(mContentResolver, which, dflt);
+ }
+
+ private void setNetDnsProperty(int which, String value) {
+ final String key = "net.dns" + which;
+ // Log and forget errors setting unsupported properties.
+ try {
+ mSystemProperties.set(key, value);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting unsupported net.dns property: ", e);
+ }
+ }
+
+ private static boolean shouldUseTls(String mode) {
+ if (TextUtils.isEmpty(mode)) {
+ mode = PRIVATE_DNS_DEFAULT_MODE;
+ }
+ return mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
+ mode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 59870cb..ff05723 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -19,7 +19,6 @@
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -43,7 +42,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
@@ -53,9 +51,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -79,7 +75,6 @@
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -88,8 +83,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -114,12 +107,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -197,8 +186,6 @@
private int mLastNotificationId;
private boolean mRndisEnabled; // track the RNDIS function enabled state
- private boolean mUsbTetherRequested; // true if USB tethering should be started
- // when RNDIS is enabled
// True iff. WiFi tethering should be started when soft AP is ready.
private boolean mWifiTetherRequested;
@@ -891,33 +878,18 @@
//
// For more explanation, see b/62552150 .
synchronized (Tethering.this.mPublicSync) {
- // Always record the state of RNDIS.
- // TODO: consider:
- // final boolean disconnected = !usbConnected;
- // if (disconnected) {
- // mRndisEnabled = false;
- // mUsbTetherRequested = false;
- // return;
- // }
- // final boolean configured = usbConnected && usbConfigured;
- // mRndisEnabled = configured ? rndisEnabled : false;
- // if (!configured) return;
- mRndisEnabled = rndisEnabled;
-
- if (usbConnected && !usbConfigured) {
- // Nothing to do here (only CONNECTED, not yet CONFIGURED).
- return;
- }
-
- // start tethering if we have a request pending
- if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
+ if (!usbConnected && mRndisEnabled) {
+ // Turn off tethering if it was enabled and there is a disconnect.
+ tetherMatchingInterfaces(
+ IControlsTethering.STATE_AVAILABLE,
+ ConnectivityManager.TETHERING_USB);
+ } else if (usbConfigured && rndisEnabled) {
+ // Tether if rndis is enabled and usb is configured.
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
}
-
- // TODO: Figure out how to remove the need for this variable.
- mUsbTetherRequested = false;
+ mRndisEnabled = usbConfigured && rndisEnabled;
}
}
@@ -1121,34 +1093,8 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
-
synchronized (mPublicSync) {
- if (enable) {
- if (mRndisEnabled) {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- } else {
- mUsbTetherRequested = true;
- usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
- }
- } else {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- if (mRndisEnabled) {
- usbManager.setCurrentFunction(null, false);
- }
- mUsbTetherRequested = false;
- }
+ usbManager.setCurrentFunction(enable ? UsbManager.USB_FUNCTION_RNDIS : null, false);
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
@@ -1205,7 +1151,7 @@
if (!mForwardedDownstreams.isEmpty()) return true;
synchronized (mPublicSync) {
- return mUsbTetherRequested || mWifiTetherRequested;
+ return mWifiTetherRequested;
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 17adb1a..2224913 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -30,6 +30,7 @@
import android.net.ip.InterfaceController;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.net.util.InterfaceParams;
import android.net.util.NetdService;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
@@ -48,7 +49,6 @@
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
@@ -120,8 +120,7 @@
private int mLastError;
private int mServingMode;
private String mMyUpstreamIfaceName; // may change over time
- private NetworkInterface mNetworkInterface;
- private byte[] mHwAddr;
+ private InterfaceParams mInterfaceParams;
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
// properties are those selected by the IPv6TetheringCoordinator and relayed
// to us. By comparison, mLinkProperties contains the addresses and directly
@@ -247,31 +246,16 @@
}
private boolean startIPv6() {
- // TODO: Refactor for testability (perhaps passing an android.system.Os
- // instance and calling getifaddrs() directly).
- try {
- mNetworkInterface = NetworkInterface.getByName(mIfaceName);
- } catch (SocketException e) {
- mLog.e("Error looking up NetworkInterfaces: " + e);
- stopIPv6();
- return false;
- }
- if (mNetworkInterface == null) {
- mLog.e("Failed to find NetworkInterface");
+ // TODO: Refactor for better testability. This is one of the things
+ // that prohibits unittesting IPv6 tethering setup.
+ mInterfaceParams = InterfaceParams.getByName(mIfaceName);
+ if (mInterfaceParams == null) {
+ mLog.e("Failed to find InterfaceParams");
stopIPv6();
return false;
}
- try {
- mHwAddr = mNetworkInterface.getHardwareAddress();
- } catch (SocketException e) {
- mLog.e("Failed to find hardware address: " + e);
- stopIPv6();
- return false;
- }
-
- final int ifindex = mNetworkInterface.getIndex();
- mRaDaemon = new RouterAdvertisementDaemon(mIfaceName, ifindex, mHwAddr);
+ mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
if (!mRaDaemon.start()) {
stopIPv6();
return false;
@@ -281,8 +265,7 @@
}
private void stopIPv6() {
- mNetworkInterface = null;
- mHwAddr = null;
+ mInterfaceParams = null;
setRaParams(null);
if (mRaDaemon != null) {
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 29b322e..d957ca0 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -25,6 +25,9 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
public class SyncJobService extends JobService {
private static final String TAG = "SyncManager";
@@ -32,7 +35,14 @@
public static final String EXTRA_MESSENGER = "messenger";
private Messenger mMessenger;
- private SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>();
+
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private final SparseArray<JobParameters> mJobParamsMap = new SparseArray<>();
+
+ @GuardedBy("mLock")
+ private final SparseBooleanArray mStartedSyncs = new SparseBooleanArray();
private final SyncLogger mLogger = SyncLogger.getInstance();
@@ -69,8 +79,10 @@
mLogger.purgeOldLogs();
boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- synchronized (jobParamsMap) {
- jobParamsMap.put(params.getJobId(), params);
+ synchronized (mLock) {
+ final int jobId = params.getJobId();
+ mJobParamsMap.put(jobId, params);
+ mStartedSyncs.delete(jobId);
}
Message m = Message.obtain();
m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
@@ -97,8 +109,18 @@
+ params.getStopReason());
}
mLogger.log("onStopJob() ", mLogger.jobParametersToString(params));
- synchronized (jobParamsMap) {
- jobParamsMap.remove(params.getJobId());
+ synchronized (mLock) {
+ final int jobId = params.getJobId();
+ mJobParamsMap.remove(jobId);
+
+ if (!mStartedSyncs.get(jobId)) {
+ final String message = "Job " + jobId + " didn't start: params=" +
+ jobParametersToString(params);
+ mLogger.log(message);
+ Slog.wtf(TAG, message);
+ }
+
+ mStartedSyncs.delete(jobId);
}
Message m = Message.obtain();
m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
@@ -117,8 +139,8 @@
}
public void callJobFinished(int jobId, boolean needsReschedule, String why) {
- synchronized (jobParamsMap) {
- JobParameters params = jobParamsMap.get(jobId);
+ synchronized (mLock) {
+ JobParameters params = mJobParamsMap.get(jobId);
mLogger.log("callJobFinished()",
" jobid=", jobId,
" needsReschedule=", needsReschedule,
@@ -126,10 +148,25 @@
" why=", why);
if (params != null) {
jobFinished(params, needsReschedule);
- jobParamsMap.remove(jobId);
+ mJobParamsMap.remove(jobId);
} else {
Slog.e(TAG, "Job params not found for " + String.valueOf(jobId));
}
}
}
+
+ public void markSyncStarted(int jobId) {
+ synchronized (mLock) {
+ mStartedSyncs.put(jobId, true);
+ }
+ }
+
+ public static String jobParametersToString(JobParameters params) {
+ if (params == null) {
+ return "job:null";
+ } else {
+ return "job:#" + params.getJobId() + ":"
+ + SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java
index 8503768..75c0181 100644
--- a/services/core/java/com/android/server/content/SyncLogger.java
+++ b/services/core/java/com/android/server/content/SyncLogger.java
@@ -233,12 +233,7 @@
@Override
public String jobParametersToString(JobParameters params) {
- if (params == null) {
- return "job:null";
- } else {
- return "job:#" + params.getJobId() + ":"
- + SyncOperation.maybeCreateFromJobExtras(params.getExtras());
- }
+ return SyncJobService.jobParametersToString(params);
}
@Override
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 965159b..ad2cf6c 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2898,6 +2898,8 @@
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
if (isLoggable) Slog.v(TAG, op.toString());
+ mSyncJobService.markSyncStarted(op.jobId);
+
if (mStorageIsLow) {
deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE, "storage low");
return;
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 0b62907..ac0e1b5 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -222,8 +222,6 @@
@Override
public boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config) {
- Slog.e(TAG,
- "setBrightnessConfiguration called on device without display information.");
return false;
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index fddb81b..6db3b44 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -19,6 +19,7 @@
import android.hardware.display.DisplayViewport;
import android.util.DisplayMetrics;
import android.view.Display;
+import android.view.DisplayCutout;
import android.view.Surface;
import java.util.Arrays;
@@ -229,6 +230,11 @@
public int flags;
/**
+ * The {@link DisplayCutout} if present or {@code null} otherwise.
+ */
+ public DisplayCutout displayCutout;
+
+ /**
* The touch attachment, per {@link DisplayViewport#touch}.
*/
public int touch;
@@ -321,6 +327,7 @@
|| appVsyncOffsetNanos != other.appVsyncOffsetNanos
|| presentationDeadlineNanos != other.presentationDeadlineNanos
|| flags != other.flags
+ || !Objects.equal(displayCutout, other.displayCutout)
|| touch != other.touch
|| rotation != other.rotation
|| type != other.type
@@ -354,6 +361,7 @@
appVsyncOffsetNanos = other.appVsyncOffsetNanos;
presentationDeadlineNanos = other.presentationDeadlineNanos;
flags = other.flags;
+ displayCutout = other.displayCutout;
touch = other.touch;
rotation = other.rotation;
type = other.type;
@@ -380,6 +388,9 @@
sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
sb.append(", presDeadline ").append(presentationDeadlineNanos);
+ if (displayCutout != null) {
+ sb.append(", cutout ").append(displayCutout);
+ }
sb.append(", touch ").append(touchToString(touch));
sb.append(", rotation ").append(rotation);
sb.append(", type ").append(Display.typeToString(type));
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e5a4b0a..d2b8e5c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -260,13 +260,6 @@
private long mScreenOnBlockStartRealTime;
private long mScreenOffBlockStartRealTime;
- // The last brightness that was set by the user and not temporary. Set to -1 when a brightness
- // has yet to be recorded.
- private int mLastBrightness;
- // The last auto brightness adjustment that was set by the user and not temporary. Set to
- // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
- private float mLastAutoBrightnessAdjustment;
-
// Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
private int mReportedScreenStateToPolicy;
@@ -299,14 +292,18 @@
@Nullable
private BrightnessMappingStrategy mBrightnessMapper;
- // The default brightness configuration. Used for whenever we don't have a valid brightness
- // configuration set. This is typically seen with users that don't have a brightness
- // configuration that's different from the default.
- private BrightnessConfiguration mDefaultBrightnessConfiguration;
-
// The current brightness configuration.
+ @Nullable
private BrightnessConfiguration mBrightnessConfiguration;
+ // The last brightness that was set by the user and not temporary. Set to -1 when a brightness
+ // has yet to be recorded.
+ private int mLastBrightness;
+
+ // The last auto brightness adjustment that was set by the user and not temporary. Set to
+ // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
+ private float mLastAutoBrightnessAdjustment;
+
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
@@ -1488,8 +1485,7 @@
}
break;
case MSG_CONFIGURE_BRIGHTNESS:
- BrightnessConfiguration c = (BrightnessConfiguration) msg.obj;
- mBrightnessConfiguration = c != null ? c : mDefaultBrightnessConfiguration;
+ mBrightnessConfiguration = (BrightnessConfiguration)msg.obj;
updatePowerState();
break;
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index eb9ff58..483b02c 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -30,9 +30,12 @@
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.Trace;
+import android.text.TextUtils;
+import android.util.PathParser;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import android.view.DisplayCutout;
import android.view.DisplayEventReceiver;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -400,12 +403,14 @@
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
}
+ mInfo.displayCutout = parseDefaultDisplayCutout(res);
mInfo.type = Display.TYPE_BUILT_IN;
mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
mInfo.xDpi = phys.xDpi;
mInfo.yDpi = phys.yDpi;
mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
} else {
+ mInfo.displayCutout = null;
mInfo.type = Display.TYPE_HDMI;
mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
mInfo.name = getContext().getResources().getString(
@@ -434,6 +439,15 @@
return mInfo;
}
+ private DisplayCutout parseDefaultDisplayCutout(Resources res) {
+ String cutoutString = res.getString(
+ com.android.internal.R.string.config_mainBuiltInDisplayCutout);
+ if (TextUtils.isEmpty(cutoutString)) {
+ return null;
+ }
+ return DisplayCutout.fromBounds(PathParser.createPathFromPathData(cutoutString));
+ }
+
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
// Assume that the brightness is off if the display is being turned off.
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 78a5407..132f083 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -145,6 +145,7 @@
mInfo.overscanRight = mOverrideDisplayInfo.overscanRight;
mInfo.overscanBottom = mOverrideDisplayInfo.overscanBottom;
mInfo.rotation = mOverrideDisplayInfo.rotation;
+ mInfo.displayCutout = mOverrideDisplayInfo.displayCutout;
mInfo.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
@@ -280,6 +281,7 @@
mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
+ mBaseDisplayInfo.displayCutout = deviceInfo.displayCutout;
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo = null;
diff --git a/services/core/java/com/android/server/job/GrantedUriPermissions.java b/services/core/java/com/android/server/job/GrantedUriPermissions.java
index c23b109..8fecb8f 100644
--- a/services/core/java/com/android/server/job/GrantedUriPermissions.java
+++ b/services/core/java/com/android/server/job/GrantedUriPermissions.java
@@ -25,6 +25,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -153,4 +154,21 @@
pw.println(mUris.get(i));
}
}
+
+ public void dump(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(GrantedUriPermissionsDumpProto.FLAGS, mGrantFlags);
+ proto.write(GrantedUriPermissionsDumpProto.SOURCE_USER_ID, mSourceUserId);
+ proto.write(GrantedUriPermissionsDumpProto.TAG, mTag);
+ proto.write(GrantedUriPermissionsDumpProto.PERMISSION_OWNER, mPermissionOwner.toString());
+ for (int i = 0; i < mUris.size(); i++) {
+ Uri u = mUris.get(i);
+ if (u != null) {
+ proto.write(GrantedUriPermissionsDumpProto.URIS, u.toString());
+ }
+ }
+
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 296743b..8b8faa3 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -28,6 +28,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.RingBufferIndices;
import com.android.server.job.controllers.JobStatus;
@@ -308,13 +309,13 @@
}
}
- void dump(PrintWriter pw, String header, String prefix, long now, long nowEllapsed,
+ void dump(PrintWriter pw, String header, String prefix, long now, long nowElapsed,
int filterUid) {
final long period = getTotalTime(now);
pw.print(prefix); pw.print(header); pw.print(" at ");
pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString());
pw.print(" (");
- TimeUtils.formatDuration(mStartElapsedTime, nowEllapsed, pw);
+ TimeUtils.formatDuration(mStartElapsedTime, nowElapsed, pw);
pw.print(") over ");
TimeUtils.formatDuration(period, pw);
pw.println(":");
@@ -365,6 +366,73 @@
pw.print(mMaxTotalActive); pw.print(" total, ");
pw.print(mMaxFgActive); pw.println(" foreground");
}
+
+ private void printPackageEntryState(ProtoOutputStream proto, long fieldId,
+ long duration, int count) {
+ final long token = proto.start(fieldId);
+ proto.write(DataSetProto.PackageEntryProto.State.DURATION_MS, duration);
+ proto.write(DataSetProto.PackageEntryProto.State.COUNT, count);
+ proto.end(token);
+ }
+
+ void dump(ProtoOutputStream proto, long fieldId, long now, long nowElapsed, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long period = getTotalTime(now);
+
+ proto.write(DataSetProto.START_CLOCK_TIME_MS, mStartClockTime);
+ proto.write(DataSetProto.ELAPSED_TIME_MS, nowElapsed - mStartElapsedTime);
+ proto.write(DataSetProto.PERIOD_MS, period);
+
+ final int NE = mEntries.size();
+ for (int i = 0; i < NE; i++) {
+ int uid = mEntries.keyAt(i);
+ if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+ continue;
+ }
+ ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+ final int NP = uidMap.size();
+ for (int j = 0; j < NP; j++) {
+ final long peToken = proto.start(DataSetProto.PACKAGE_ENTRIES);
+ PackageEntry pe = uidMap.valueAt(j);
+
+ proto.write(DataSetProto.PackageEntryProto.UID, uid);
+ proto.write(DataSetProto.PackageEntryProto.PACKAGE_NAME, uidMap.keyAt(j));
+
+ printPackageEntryState(proto, DataSetProto.PackageEntryProto.PENDING_STATE,
+ pe.getPendingTime(now), pe.pendingCount);
+ printPackageEntryState(proto, DataSetProto.PackageEntryProto.ACTIVE_STATE,
+ pe.getActiveTime(now), pe.activeCount);
+ printPackageEntryState(proto, DataSetProto.PackageEntryProto.ACTIVE_TOP_STATE,
+ pe.getActiveTopTime(now), pe.activeTopCount);
+
+ proto.write(DataSetProto.PackageEntryProto.PENDING,
+ pe.pendingNesting > 0 || pe.hadPending);
+ proto.write(DataSetProto.PackageEntryProto.ACTIVE,
+ pe.activeNesting > 0 || pe.hadActive);
+ proto.write(DataSetProto.PackageEntryProto.ACTIVE_TOP,
+ pe.activeTopNesting > 0 || pe.hadActiveTop);
+
+ for (int k = 0; k < pe.stopReasons.size(); k++) {
+ final long srcToken =
+ proto.start(DataSetProto.PackageEntryProto.STOP_REASONS);
+
+ proto.write(DataSetProto.PackageEntryProto.StopReasonCount.REASON,
+ pe.stopReasons.keyAt(k));
+ proto.write(DataSetProto.PackageEntryProto.StopReasonCount.COUNT,
+ pe.stopReasons.valueAt(k));
+
+ proto.end(srcToken);
+ }
+
+ proto.end(peToken);
+ }
+ }
+
+ proto.write(DataSetProto.MAX_CONCURRENCY, mMaxTotalActive);
+ proto.write(DataSetProto.MAX_FOREGROUND_CONCURRENCY, mMaxFgActive);
+
+ proto.end(token);
+ }
}
void rebatchIfNeeded(long now) {
@@ -450,7 +518,7 @@
public void dump(PrintWriter pw, String prefix, int filterUid) {
final long now = sUptimeMillisClock.millis();
- final long nowEllapsed = sElapsedRealtimeClock.millis();
+ final long nowElapsed = sElapsedRealtimeClock.millis();
final DataSet total;
if (mLastDataSets[0] != null) {
total = new DataSet(mLastDataSets[0]);
@@ -461,11 +529,37 @@
mCurDataSet.addTo(total, now);
for (int i = 1; i < mLastDataSets.length; i++) {
if (mLastDataSets[i] != null) {
- mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowEllapsed, filterUid);
+ mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowElapsed, filterUid);
pw.println();
}
}
- total.dump(pw, "Current stats", prefix, now, nowEllapsed, filterUid);
+ total.dump(pw, "Current stats", prefix, now, nowElapsed, filterUid);
+ }
+
+ public void dump(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long now = sUptimeMillisClock.millis();
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+
+ final DataSet total;
+ if (mLastDataSets[0] != null) {
+ total = new DataSet(mLastDataSets[0]);
+ mLastDataSets[0].addTo(total, now);
+ } else {
+ total = new DataSet(mCurDataSet);
+ }
+ mCurDataSet.addTo(total, now);
+
+ for (int i = 1; i < mLastDataSets.length; i++) {
+ if (mLastDataSets[i] != null) {
+ mLastDataSets[i].dump(proto, JobPackageTrackerDumpProto.HISTORICAL_STATS,
+ now, nowElapsed, filterUid);
+ }
+ }
+ total.dump(proto, JobPackageTrackerDumpProto.CURRENT_STATS,
+ now, nowElapsed, filterUid);
+
+ proto.end(token);
}
public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
@@ -512,4 +606,40 @@
}
return true;
}
+
+ public void dumpHistory(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final int size = mEventIndices.size();
+ if (size == 0) {
+ return;
+ }
+ final long token = proto.start(fieldId);
+
+ final long now = sElapsedRealtimeClock.millis();
+ for (int i = 0; i < size; i++) {
+ final int index = mEventIndices.indexOf(i);
+ final int uid = mEventUids[index];
+ if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+ continue;
+ }
+ final int cmd = mEventCmds[index] & EVENT_CMD_MASK;
+ if (cmd == EVENT_NULL) {
+ continue;
+ }
+ final long heToken = proto.start(JobPackageHistoryProto.HISTORY_EVENT);
+
+ proto.write(JobPackageHistoryProto.HistoryEvent.EVENT, cmd);
+ proto.write(JobPackageHistoryProto.HistoryEvent.TIME_SINCE_EVENT_MS, now - mEventTimes[index]);
+ proto.write(JobPackageHistoryProto.HistoryEvent.UID, uid);
+ proto.write(JobPackageHistoryProto.HistoryEvent.JOB_ID, mEventJobIds[index]);
+ proto.write(JobPackageHistoryProto.HistoryEvent.TAG, mEventTags[index]);
+ if (cmd == EVENT_STOP_JOB || cmd == EVENT_STOP_PERIODIC_JOB) {
+ proto.write(JobPackageHistoryProto.HistoryEvent.STOP_REASON,
+ (mEventCmds[index] & EVENT_STOP_REASON_MASK) >> EVENT_STOP_REASON_SHIFT);
+ }
+
+ proto.end(heToken);
+ }
+
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index bcb57ef..733ed3d 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -64,6 +64,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
@@ -74,6 +75,8 @@
import com.android.server.DeviceIdleController;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
+import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
import com.android.server.job.JobStore.JobStatusFunctor;
import com.android.server.job.controllers.AppIdleController;
import com.android.server.job.controllers.BackgroundJobsController;
@@ -185,13 +188,18 @@
boolean mReportedActive;
/**
+ * Are we currently in device-wide standby parole?
+ */
+ volatile boolean mInParole;
+
+ /**
* Current limit on the number of concurrent JobServiceContext entries we want to
* keep actively running a job.
*/
int mMaxActiveJobs = 1;
/**
- * Which uids are currently in the foreground.
+ * A mapping of which uids are currently in the foreground to their effective priority.
*/
final SparseIntArray mUidPriorityOverride = new SparseIntArray();
@@ -466,11 +474,11 @@
DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT);
MAX_WORK_RESCHEDULE_COUNT = mParser.getInt(KEY_MAX_WORK_RESCHEDULE_COUNT,
DEFAULT_MAX_WORK_RESCHEDULE_COUNT);
- MIN_LINEAR_BACKOFF_TIME = mParser.getLong(KEY_MIN_LINEAR_BACKOFF_TIME,
+ MIN_LINEAR_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_LINEAR_BACKOFF_TIME,
DEFAULT_MIN_LINEAR_BACKOFF_TIME);
- MIN_EXP_BACKOFF_TIME = mParser.getLong(KEY_MIN_EXP_BACKOFF_TIME,
+ MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME,
DEFAULT_MIN_EXP_BACKOFF_TIME);
- STANDBY_HEARTBEAT_TIME = mParser.getLong(KEY_STANDBY_HEARTBEAT_TIME,
+ STANDBY_HEARTBEAT_TIME = mParser.getDurationMillis(KEY_STANDBY_HEARTBEAT_TIME,
DEFAULT_STANDBY_HEARTBEAT_TIME);
STANDBY_BEATS[1] = mParser.getInt(KEY_STANDBY_WORKING_BEATS,
DEFAULT_STANDBY_WORKING_BEATS);
@@ -549,6 +557,36 @@
}
pw.println('}');
}
+
+ void dump(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(ConstantsProto.MIN_IDLE_COUNT, MIN_IDLE_COUNT);
+ proto.write(ConstantsProto.MIN_CHARGING_COUNT, MIN_CHARGING_COUNT);
+ proto.write(ConstantsProto.MIN_BATTERY_NOT_LOW_COUNT, MIN_BATTERY_NOT_LOW_COUNT);
+ proto.write(ConstantsProto.MIN_STORAGE_NOT_LOW_COUNT, MIN_STORAGE_NOT_LOW_COUNT);
+ proto.write(ConstantsProto.MIN_CONNECTIVITY_COUNT, MIN_CONNECTIVITY_COUNT);
+ proto.write(ConstantsProto.MIN_CONTENT_COUNT, MIN_CONTENT_COUNT);
+ proto.write(ConstantsProto.MIN_READY_JOBS_COUNT, MIN_READY_JOBS_COUNT);
+ proto.write(ConstantsProto.HEAVY_USE_FACTOR, HEAVY_USE_FACTOR);
+ proto.write(ConstantsProto.MODERATE_USE_FACTOR, MODERATE_USE_FACTOR);
+ proto.write(ConstantsProto.FG_JOB_COUNT, FG_JOB_COUNT);
+ proto.write(ConstantsProto.BG_NORMAL_JOB_COUNT, BG_NORMAL_JOB_COUNT);
+ proto.write(ConstantsProto.BG_MODERATE_JOB_COUNT, BG_MODERATE_JOB_COUNT);
+ proto.write(ConstantsProto.BG_LOW_JOB_COUNT, BG_LOW_JOB_COUNT);
+ proto.write(ConstantsProto.BG_CRITICAL_JOB_COUNT, BG_CRITICAL_JOB_COUNT);
+ proto.write(ConstantsProto.MAX_STANDARD_RESCHEDULE_COUNT, MAX_STANDARD_RESCHEDULE_COUNT);
+ proto.write(ConstantsProto.MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT);
+ proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME);
+ proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
+ proto.write(ConstantsProto.STANDBY_HEARTBEAT_TIME_MS, STANDBY_HEARTBEAT_TIME);
+
+ for (int period : STANDBY_BEATS) {
+ proto.write(ConstantsProto.STANDBY_BEATS, period);
+ }
+
+ proto.end(token);
+ }
}
final Constants mConstants;
@@ -927,7 +965,7 @@
// with just the foreground priority. This means that persistent processes
// can never be the top app priority... that is fine.
mUidPriorityOverride.put(uid, JobInfo.PRIORITY_TOP_APP);
- } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+ } else if (procState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_APP);
} else {
mUidPriorityOverride.delete(uid);
@@ -1720,28 +1758,31 @@
}
// If the app is in a non-active standby bucket, make sure we've waited
- // an appropriate amount of time since the last invocation
- final int bucket = job.getStandbyBucket();
- if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
- // Only skip this job if it's still waiting for the end of its (initial) nominal
- // bucket interval. Once it's waited that long, we let it go ahead and clear.
- // The final (NEVER) bucket is special; we never age those apps' jobs into
- // runnability.
- if (bucket >= mConstants.STANDBY_BEATS.length
- || (mHeartbeat < job.getBaseHeartbeat() + mConstants.STANDBY_BEATS[bucket])) {
- // TODO: log/trace that we're deferring the job due to bucketing if we hit this
- if (job.getWhenStandbyDeferred() == 0) {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
- + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+ // an appropriate amount of time since the last invocation. During device-
+ // wide parole, standby bucketing is ignored.
+ if (!mInParole) {
+ final int bucket = job.getStandbyBucket();
+ if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
+ // Only skip this job if it's still waiting for the end of its (initial) nominal
+ // bucket interval. Once it's waited that long, we let it go ahead and clear.
+ // The final (NEVER) bucket is special; we never age those apps' jobs into
+ // runnability.
+ if (bucket >= mConstants.STANDBY_BEATS.length
+ || (mHeartbeat < job.getBaseHeartbeat() + mConstants.STANDBY_BEATS[bucket])) {
+ // TODO: log/trace that we're deferring the job due to bucketing if we hit this
+ if (job.getWhenStandbyDeferred() == 0) {
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
+ + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+ }
+ job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
}
- job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
- }
- return false;
- } else {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Bucket deferred job aged into runnability at "
- + mHeartbeat + " : " + job);
+ return false;
+ } else {
+ if (DEBUG_STANDBY) {
+ Slog.v(TAG, "Bucket deferred job aged into runnability at "
+ + mHeartbeat + " : " + job);
+ }
}
}
}
@@ -2086,7 +2127,10 @@
@Override
public void onParoleStateChanged(boolean isParoleOn) {
- // Unused
+ if (DEBUG_STANDBY) {
+ Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+ }
+ mInParole = isParoleOn;
}
}
@@ -2322,9 +2366,46 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
+ int filterUid = -1;
+ boolean proto = false;
+ if (!ArrayUtils.isEmpty(args)) {
+ int opti = 0;
+ while (opti < args.length) {
+ String arg = args[opti];
+ if ("-h".equals(arg)) {
+ dumpHelp(pw);
+ return;
+ } else if ("-a".equals(arg)) {
+ // Ignore, we always dump all.
+ } else if ("--proto".equals(arg)) {
+ proto = true;
+ } else if (arg.length() > 0 && arg.charAt(0) == '-') {
+ pw.println("Unknown option: " + arg);
+ return;
+ } else {
+ break;
+ }
+ opti++;
+ }
+ if (opti < args.length) {
+ String pkg = args[opti];
+ try {
+ filterUid = getContext().getPackageManager().getPackageUid(pkg,
+ PackageManager.MATCH_ANY_USER);
+ } catch (NameNotFoundException ignored) {
+ pw.println("Invalid package: " + pkg);
+ return;
+ }
+ }
+ }
+
long identityToken = Binder.clearCallingIdentity();
try {
- JobSchedulerService.this.dumpInternal(pw, args);
+ if (proto) {
+ JobSchedulerService.this.dumpInternalProto(fd, filterUid);
+ } else {
+ JobSchedulerService.this.dumpInternal(pw, filterUid);
+ }
} finally {
Binder.restoreCallingIdentity(identityToken);
}
@@ -2589,37 +2670,24 @@
pw.println(" [package] is an optional package name to limit the output to.");
}
- void dumpInternal(final PrintWriter pw, String[] args) {
- int filterUid = -1;
- if (!ArrayUtils.isEmpty(args)) {
- int opti = 0;
- while (opti < args.length) {
- String arg = args[opti];
- if ("-h".equals(arg)) {
- dumpHelp(pw);
- return;
- } else if ("-a".equals(arg)) {
- // Ignore, we always dump all.
- } else if (arg.length() > 0 && arg.charAt(0) == '-') {
- pw.println("Unknown option: " + arg);
- return;
- } else {
- break;
+ /** Sort jobs by caller UID, then by Job ID. */
+ private static void sortJobs(List<JobStatus> jobs) {
+ Collections.sort(jobs, new Comparator<JobStatus>() {
+ @Override
+ public int compare(JobStatus o1, JobStatus o2) {
+ int uid1 = o1.getUid();
+ int uid2 = o2.getUid();
+ int id1 = o1.getJobId();
+ int id2 = o2.getJobId();
+ if (uid1 != uid2) {
+ return uid1 < uid2 ? -1 : 1;
}
- opti++;
+ return id1 < id2 ? -1 : (id1 > id2 ? 1 : 0);
}
- if (opti < args.length) {
- String pkg = args[opti];
- try {
- filterUid = getContext().getPackageManager().getPackageUid(pkg,
- PackageManager.MATCH_ANY_USER);
- } catch (NameNotFoundException ignored) {
- pw.println("Invalid package: " + pkg);
- return;
- }
- }
- }
+ });
+ }
+ void dumpInternal(final PrintWriter pw, int filterUid) {
final int filterUidFinal = UserHandle.getAppId(filterUid);
final long nowElapsed = sElapsedRealtimeClock.millis();
final long nowUptime = sUptimeMillisClock.millis();
@@ -2632,19 +2700,7 @@
pw.println(" jobs:");
if (mJobs.size() > 0) {
final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
- Collections.sort(jobs, new Comparator<JobStatus>() {
- @Override
- public int compare(JobStatus o1, JobStatus o2) {
- int uid1 = o1.getUid();
- int uid2 = o2.getUid();
- int id1 = o1.getJobId();
- int id2 = o2.getJobId();
- if (uid1 != uid2) {
- return uid1 < uid2 ? -1 : 1;
- }
- return id1 < id2 ? -1 : (id1 > id2 ? 1 : 0);
- }
- });
+ sortJobs(jobs);
for (JobStatus job : jobs) {
pw.print(" JOB #"); job.printUniqueId(pw); pw.print(": ");
pw.println(job.toShortStringExceptUniqueId());
@@ -2781,4 +2837,144 @@
}
pw.println();
}
+
+ void dumpInternalProto(final FileDescriptor fd, int filterUid) {
+ ProtoOutputStream proto = new ProtoOutputStream(fd);
+ final int filterUidFinal = UserHandle.getAppId(filterUid);
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ final long nowUptime = sUptimeMillisClock.millis();
+
+ synchronized (mLock) {
+ mConstants.dump(proto, JobSchedulerServiceDumpProto.SETTINGS);
+ for (int u : mStartedUsers) {
+ proto.write(JobSchedulerServiceDumpProto.STARTED_USERS, u);
+ }
+ if (mJobs.size() > 0) {
+ final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
+ sortJobs(jobs);
+ for (JobStatus job : jobs) {
+ final long rjToken = proto.start(JobSchedulerServiceDumpProto.REGISTERED_JOBS);
+ job.writeToShortProto(proto, JobSchedulerServiceDumpProto.RegisteredJob.INFO);
+
+ // Skip printing details if the caller requested a filter
+ if (!job.shouldDump(filterUidFinal)) {
+ continue;
+ }
+
+ job.dump(proto, JobSchedulerServiceDumpProto.RegisteredJob.DUMP, true, nowElapsed);
+
+ // isReadyToBeExecuted
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_READY,
+ job.isReady());
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_USER_STARTED,
+ ArrayUtils.contains(mStartedUsers, job.getUserId()));
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_PENDING,
+ mPendingJobs.contains(job));
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_CURRENTLY_ACTIVE,
+ isCurrentlyActiveLocked(job));
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_UID_BACKING_UP,
+ mBackingUpUids.indexOfKey(job.getSourceUid()) >= 0);
+ boolean componentPresent = false;
+ try {
+ componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+ job.getServiceComponent(),
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ job.getUserId()) != null);
+ } catch (RemoteException e) {
+ }
+ proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_COMPONENT_PRESENT,
+ componentPresent);
+
+ proto.end(rjToken);
+ }
+ }
+ for (StateController controller : mControllers) {
+ controller.dumpControllerStateLocked(
+ proto, JobSchedulerServiceDumpProto.CONTROLLERS, filterUidFinal);
+ }
+ for (int i=0; i< mUidPriorityOverride.size(); i++) {
+ int uid = mUidPriorityOverride.keyAt(i);
+ if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+ long pToken = proto.start(JobSchedulerServiceDumpProto.PRIORITY_OVERRIDES);
+ proto.write(JobSchedulerServiceDumpProto.PriorityOverride.UID, uid);
+ proto.write(JobSchedulerServiceDumpProto.PriorityOverride.OVERRIDE_VALUE,
+ mUidPriorityOverride.valueAt(i));
+ proto.end(pToken);
+ }
+ }
+ for (int i = 0; i < mBackingUpUids.size(); i++) {
+ int uid = mBackingUpUids.keyAt(i);
+ if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+ proto.write(JobSchedulerServiceDumpProto.BACKING_UP_UIDS, uid);
+ }
+ }
+
+ mJobPackageTracker.dump(proto, JobSchedulerServiceDumpProto.PACKAGE_TRACKER,
+ filterUidFinal);
+ mJobPackageTracker.dumpHistory(proto, JobSchedulerServiceDumpProto.HISTORY,
+ filterUidFinal);
+
+ for (JobStatus job : mPendingJobs) {
+ final long pjToken = proto.start(JobSchedulerServiceDumpProto.PENDING_JOBS);
+
+ job.writeToShortProto(proto, PendingJob.INFO);
+ job.dump(proto, PendingJob.DUMP, false, nowElapsed);
+ int priority = evaluateJobPriorityLocked(job);
+ if (priority != JobInfo.PRIORITY_DEFAULT) {
+ proto.write(PendingJob.EVALUATED_PRIORITY, priority);
+ }
+ proto.write(PendingJob.ENQUEUED_DURATION_MS, nowUptime - job.madePending);
+
+ proto.end(pjToken);
+ }
+ for (JobServiceContext jsc : mActiveServices) {
+ final long ajToken = proto.start(JobSchedulerServiceDumpProto.ACTIVE_JOBS);
+ final JobStatus job = jsc.getRunningJobLocked();
+
+ if (job == null) {
+ final long ijToken = proto.start(ActiveJob.INACTIVE);
+
+ proto.write(ActiveJob.InactiveJob.TIME_SINCE_STOPPED_MS,
+ nowElapsed - jsc.mStoppedTime);
+ if (jsc.mStoppedReason != null) {
+ proto.write(ActiveJob.InactiveJob.STOPPED_REASON,
+ jsc.mStoppedReason);
+ }
+
+ proto.end(ijToken);
+ } else {
+ final long rjToken = proto.start(ActiveJob.RUNNING);
+
+ job.writeToShortProto(proto, ActiveJob.RunningJob.INFO);
+
+ proto.write(ActiveJob.RunningJob.RUNNING_DURATION_MS,
+ nowElapsed - jsc.getExecutionStartTimeElapsed());
+ proto.write(ActiveJob.RunningJob.TIME_UNTIL_TIMEOUT_MS,
+ jsc.getTimeoutElapsed() - nowElapsed);
+
+ job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed);
+
+ int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
+ if (priority != JobInfo.PRIORITY_DEFAULT) {
+ proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY, priority);
+ }
+
+ proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS,
+ nowUptime - job.madeActive);
+ proto.write(ActiveJob.RunningJob.PENDING_DURATION_MS,
+ job.madeActive - job.madePending);
+
+ proto.end(rjToken);
+ }
+ proto.end(ajToken);
+ }
+ if (filterUid == -1) {
+ proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock);
+ proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive);
+ proto.write(JobSchedulerServiceDumpProto.MAX_ACTIVE_JOBS, mMaxActiveJobs);
+ }
+ }
+
+ proto.flush();
+ }
}
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 6a3fd04..709deeb 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -38,12 +38,14 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
+import com.android.server.EventLogTags;
import com.android.server.job.controllers.JobStatus;
/**
@@ -222,17 +224,20 @@
isDeadlineExpired, triggeredUris, triggeredAuthorities, job.network);
mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis();
- if (DEBUG_STANDBY) {
- final long whenDeferred = job.getWhenStandbyDeferred();
- if (whenDeferred > 0) {
+ final long whenDeferred = job.getWhenStandbyDeferred();
+ if (whenDeferred > 0) {
+ final long deferral = mExecutionStartTimeElapsed - whenDeferred;
+ EventLog.writeEvent(EventLogTags.JOB_DEFERRED_EXECUTION, deferral);
+ if (DEBUG_STANDBY) {
StringBuilder sb = new StringBuilder(128);
sb.append("Starting job deferred for standby by ");
- TimeUtils.formatDuration(mExecutionStartTimeElapsed - whenDeferred, sb);
- sb.append(" : ");
+ TimeUtils.formatDuration(deferral, sb);
+ sb.append(" ms : ");
sb.append(job.toShortString());
Slog.v(TAG, sb.toString());
}
}
+
// Once we'e begun executing a job, we by definition no longer care whether
// it was inflated from disk with not-yet-coherent delay/deadline bounds.
job.clearPersistedUtcTimes();
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index a7ed2f5..8d11d1e 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -20,10 +20,12 @@
import android.content.Context;
import android.os.UserHandle;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -152,6 +154,38 @@
});
}
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.APP_IDLE);
+
+ proto.write(StateControllerProto.AppIdleController.IS_PAROLE_ON, mAppIdleParoleOn);
+
+ mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
+ @Override public void process(JobStatus js) {
+ // Skip printing details if the caller requested a filter
+ if (!js.shouldDump(filterUid)) {
+ return;
+ }
+
+ final long jsToken =
+ proto.start(StateControllerProto.AppIdleController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.AppIdleController.TrackedJob.INFO);
+ proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_PACKAGE_NAME,
+ js.getSourcePackageName());
+ proto.write(
+ StateControllerProto.AppIdleController.TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+ (js.satisfiedConstraints & JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
+ proto.end(jsToken);
+ }
+ });
+
+ proto.end(mToken);
+ proto.end(token);
+ }
+
void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
// Flag if any app's idle state has changed
boolean changed = false;
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
index fc4015d..5f95f1a 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -22,12 +22,15 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
import com.android.server.ForceAppStandbyTracker;
import com.android.server.ForceAppStandbyTracker.Listener;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.BackgroundJobsController.TrackedJob;
import java.io.PrintWriter;
@@ -90,6 +93,7 @@
return;
}
final int uid = jobStatus.getSourceUid();
+ final String sourcePkg = jobStatus.getSourcePackageName();
pw.print(" #");
jobStatus.printUniqueId(pw);
pw.print(" from ");
@@ -100,11 +104,10 @@
pw.print(", whitelisted");
}
pw.print(": ");
- pw.print(jobStatus.getSourcePackageName());
+ pw.print(sourcePkg);
pw.print(" [RUN_ANY_IN_BACKGROUND ");
- pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
- jobStatus.getSourceUid(), jobStatus.getSourcePackageName())
+ pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
? "allowed]" : "disallowed]");
if ((jobStatus.satisfiedConstraints
@@ -116,6 +119,51 @@
});
}
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.BACKGROUND);
+
+ mForceAppStandbyTracker.dumpProto(proto,
+ StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
+
+ mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
+ if (!jobStatus.shouldDump(filterUid)) {
+ return;
+ }
+ final long jsToken =
+ proto.start(StateControllerProto.BackgroundJobsController.TRACKED_JOBS);
+
+ jobStatus.writeToShortProto(proto,
+ TrackedJob.INFO);
+ final int sourceUid = jobStatus.getSourceUid();
+ proto.write(TrackedJob.SOURCE_UID, sourceUid);
+ final String sourcePkg = jobStatus.getSourcePackageName();
+ proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
+
+ proto.write(TrackedJob.IS_IN_FOREGROUND,
+ mForceAppStandbyTracker.isInForeground(sourceUid));
+ proto.write(TrackedJob.IS_WHITELISTED,
+ mForceAppStandbyTracker.isUidPowerSaveWhitelisted(sourceUid) ||
+ mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(sourceUid));
+
+ proto.write(
+ TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
+ mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
+ sourceUid, sourcePkg));
+
+ proto.write(
+ TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+ (jobStatus.satisfiedConstraints &
+ JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0);
+
+ proto.end(jsToken);
+ });
+
+ proto.end(mToken);
+ proto.end(token);
+ }
+
private void updateAllJobRestrictionsLocked() {
updateJobRestrictionsLocked(/*filterUid=*/ -1);
}
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index 76ff834..8d3d116 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -27,11 +27,13 @@
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -263,4 +265,35 @@
pw.println();
}
}
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.BATTERY);
+
+ proto.write(StateControllerProto.BatteryController.IS_ON_STABLE_POWER,
+ mChargeTracker.isOnStablePower());
+ proto.write(StateControllerProto.BatteryController.IS_BATTERY_NOT_LOW,
+ mChargeTracker.isBatteryNotLow());
+
+ proto.write(StateControllerProto.BatteryController.IS_MONITORING,
+ mChargeTracker.isMonitoring());
+ proto.write(StateControllerProto.BatteryController.LAST_BROADCAST_SEQUENCE_NUMBER,
+ mChargeTracker.getSeq());
+
+ for (int i = 0; i < mTrackedTasks.size(); i++) {
+ final JobStatus js = mTrackedTasks.valueAt(i);
+ if (!js.shouldDump(filterUid)) {
+ continue;
+ }
+ final long jsToken = proto.start(StateControllerProto.BatteryController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.BatteryController.TrackedJob.INFO);
+ proto.write(StateControllerProto.BatteryController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ proto.end(jsToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index da28769..03fd7b3 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -25,17 +25,20 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkPolicyManager;
+import android.net.NetworkRequest;
import android.net.TrafficStats;
import android.os.Process;
import android.os.UserHandle;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobServiceContext;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -290,4 +293,32 @@
}
}
}
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
+
+ proto.write(StateControllerProto.ConnectivityController.IS_CONNECTED, mConnected);
+
+ for (int i = 0; i < mTrackedJobs.size(); i++) {
+ final JobStatus js = mTrackedJobs.valueAt(i);
+ if (!js.shouldDump(filterUid)) {
+ continue;
+ }
+ final long jsToken = proto.start(StateControllerProto.ConnectivityController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.ConnectivityController.TrackedJob.INFO);
+ proto.write(StateControllerProto.ConnectivityController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ NetworkRequest rn = js.getJob().getRequiredNetwork();
+ if (rn != null) {
+ rn.writeToProto(proto,
+ StateControllerProto.ConnectivityController.TrackedJob.REQUIRED_NETWORK);
+ }
+ proto.end(jsToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
index ff807ec..7394e23f 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -28,10 +28,13 @@
import android.util.TimeUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.ContentObserverController.Observer.TriggerContentData;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -451,4 +454,103 @@
}
}
}
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.CONTENT_OBSERVER);
+
+ for (int i = 0; i < mTrackedTasks.size(); i++) {
+ JobStatus js = mTrackedTasks.valueAt(i);
+ if (!js.shouldDump(filterUid)) {
+ continue;
+ }
+ final long jsToken =
+ proto.start(StateControllerProto.ContentObserverController.TRACKED_JOBS);
+ js.writeToShortProto(proto,
+ StateControllerProto.ContentObserverController.TrackedJob.INFO);
+ proto.write(StateControllerProto.ContentObserverController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ proto.end(jsToken);
+ }
+
+ final int n = mObservers.size();
+ for (int userIdx = 0; userIdx < n; userIdx++) {
+ final long oToken =
+ proto.start(StateControllerProto.ContentObserverController.OBSERVERS);
+ final int userId = mObservers.keyAt(userIdx);
+
+ proto.write(StateControllerProto.ContentObserverController.Observer.USER_ID, userId);
+
+ ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
+ mObservers.get(userId);
+ int numbOfObserversPerUser = observersOfUser.size();
+ for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) {
+ ObserverInstance obs = observersOfUser.valueAt(observerIdx);
+ int m = obs.mJobs.size();
+ boolean shouldDump = false;
+ for (int j = 0; j < m; j++) {
+ JobInstance inst = obs.mJobs.valueAt(j);
+ if (inst.mJobStatus.shouldDump(filterUid)) {
+ shouldDump = true;
+ break;
+ }
+ }
+ if (!shouldDump) {
+ continue;
+ }
+ final long tToken = proto.start(
+ StateControllerProto.ContentObserverController.Observer.TRIGGERS);
+
+ JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx);
+ Uri u = trigger.getUri();
+ if (u != null) {
+ proto.write(TriggerContentData.URI, u.toString());
+ }
+ proto.write(TriggerContentData.FLAGS, trigger.getFlags());
+
+ for (int j = 0; j < m; j++) {
+ final long jToken = proto.start(TriggerContentData.JOBS);
+ JobInstance inst = obs.mJobs.valueAt(j);
+
+ inst.mJobStatus.writeToShortProto(proto, TriggerContentData.JobInstance.INFO);
+ proto.write(TriggerContentData.JobInstance.SOURCE_UID,
+ inst.mJobStatus.getSourceUid());
+
+ if (inst.mChangedAuthorities == null) {
+ proto.end(jToken);
+ continue;
+ }
+ if (inst.mTriggerPending) {
+ proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_UPDATE_DELAY_MS,
+ inst.mJobStatus.getTriggerContentUpdateDelay());
+ proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_MAX_DELAY_MS,
+ inst.mJobStatus.getTriggerContentMaxDelay());
+ }
+ for (int k = 0; k < inst.mChangedAuthorities.size(); k++) {
+ proto.write(TriggerContentData.JobInstance.CHANGED_AUTHORITIES,
+ inst.mChangedAuthorities.valueAt(k));
+ }
+ if (inst.mChangedUris != null) {
+ for (int k = 0; k < inst.mChangedUris.size(); k++) {
+ u = inst.mChangedUris.valueAt(k);
+ if (u != null) {
+ proto.write(TriggerContentData.JobInstance.CHANGED_URIS,
+ u.toString());
+ }
+ }
+ }
+
+ proto.end(jToken);
+ }
+
+ proto.end(tToken);
+ }
+
+ proto.end(oToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index b7eb9e0..0dbcbee 100644
--- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -29,12 +29,15 @@
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.DeviceIdleJobsController.TrackedJob;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -270,6 +273,38 @@
});
}
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.DEVICE_IDLE);
+
+ proto.write(StateControllerProto.DeviceIdleJobsController.IS_DEVICE_IDLE_MODE,
+ mDeviceIdleMode);
+ mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
+ @Override public void process(JobStatus jobStatus) {
+ if (!jobStatus.shouldDump(filterUid)) {
+ return;
+ }
+ final long jsToken =
+ proto.start(StateControllerProto.DeviceIdleJobsController.TRACKED_JOBS);
+
+ jobStatus.writeToShortProto(proto, TrackedJob.INFO);
+ proto.write(TrackedJob.SOURCE_UID, jobStatus.getSourceUid());
+ proto.write(TrackedJob.SOURCE_PACKAGE_NAME, jobStatus.getSourcePackageName());
+ proto.write(TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+ (jobStatus.satisfiedConstraints &
+ JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
+ proto.write(TrackedJob.IS_DOZE_WHITELISTED, jobStatus.dozeWhitelisted);
+ proto.write(TrackedJob.IS_ALLOWED_IN_DOZE, mAllowInIdleJobs.contains(jobStatus));
+
+ proto.end(jsToken);
+ }
+ });
+
+ proto.end(mToken);
+ proto.end(token);
+ }
+
final class DeviceIdleUpdateFunctor implements JobStore.JobStatusFunctor {
boolean mChanged;
@@ -300,4 +335,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index 7bde174..a9bc7e0 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -27,10 +27,12 @@
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
@@ -216,4 +218,27 @@
pw.println();
}
}
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.IDLE);
+
+ proto.write(StateControllerProto.IdleController.IS_IDLE, mIdleTracker.isIdle());
+
+ for (int i = 0; i < mTrackedTasks.size(); i++) {
+ final JobStatus js = mTrackedTasks.valueAt(i);
+ if (!js.shouldDump(filterUid)) {
+ continue;
+ }
+ final long jsToken = proto.start(StateControllerProto.IdleController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.IdleController.TrackedJob.INFO);
+ proto.write(StateControllerProto.IdleController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ proto.end(jsToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index e71b8ec..8f68713 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -33,11 +33,14 @@
import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.server.LocalServices;
import com.android.server.job.GrantedUriPermissions;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStatusDumpProto;
+import com.android.server.job.JobStatusShortInfoProto;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -968,6 +971,20 @@
return sb.toString();
}
+ /**
+ * Convenience function to dump data that identifies a job uniquely to proto. This is intended
+ * to mimic {@link #toShortString}.
+ */
+ public void writeToShortProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(JobStatusShortInfoProto.CALLING_UID, callingUid);
+ proto.write(JobStatusShortInfoProto.JOB_ID, job.getId());
+ proto.write(JobStatusShortInfoProto.BATTERY_NAME, batteryName);
+
+ proto.end(token);
+ }
+
void dumpConstraints(PrintWriter pw, int constraints) {
if ((constraints&CONSTRAINT_CHARGING) != 0) {
pw.print(" CHARGING");
@@ -1001,6 +1018,40 @@
}
}
+ /** Writes constraints to the given repeating proto field. */
+ void dumpConstraints(ProtoOutputStream proto, long fieldId, int constraints) {
+ if ((constraints & CONSTRAINT_CHARGING) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CHARGING);
+ }
+ if ((constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_BATTERY_NOT_LOW);
+ }
+ if ((constraints & CONSTRAINT_STORAGE_NOT_LOW) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_STORAGE_NOT_LOW);
+ }
+ if ((constraints & CONSTRAINT_TIMING_DELAY) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_TIMING_DELAY);
+ }
+ if ((constraints & CONSTRAINT_DEADLINE) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_DEADLINE);
+ }
+ if ((constraints & CONSTRAINT_IDLE) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_IDLE);
+ }
+ if ((constraints & CONSTRAINT_CONNECTIVITY) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONNECTIVITY);
+ }
+ if ((constraints & CONSTRAINT_APP_NOT_IDLE) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_APP_NOT_IDLE);
+ }
+ if ((constraints & CONSTRAINT_CONTENT_TRIGGER) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONTENT_TRIGGER);
+ }
+ if ((constraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
+ proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_DEVICE_NOT_DOZING);
+ }
+ }
+
private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) {
pw.print(prefix); pw.print(" #"); pw.print(index); pw.print(": #");
pw.print(work.getWorkId()); pw.print(" "); pw.print(work.getDeliveryCount());
@@ -1011,6 +1062,22 @@
}
}
+ private void dumpJobWorkItem(ProtoOutputStream proto, long fieldId, JobWorkItem work) {
+ final long token = proto.start(fieldId);
+
+ proto.write(JobStatusDumpProto.JobWorkItem.WORK_ID, work.getWorkId());
+ proto.write(JobStatusDumpProto.JobWorkItem.DELIVERY_COUNT, work.getDeliveryCount());
+ if (work.getIntent() != null) {
+ work.getIntent().writeToProto(proto, JobStatusDumpProto.JobWorkItem.INTENT);
+ }
+ Object grants = work.getGrants();
+ if (grants != null) {
+ ((GrantedUriPermissions) grants).dump(proto, JobStatusDumpProto.JobWorkItem.URI_GRANTS);
+ }
+
+ proto.end(token);
+ }
+
// normalized bucket indices, not the AppStandby constants
private String bucketName(int bucket) {
switch (bucket) {
@@ -1198,4 +1265,168 @@
pw.println(t.format(format));
}
}
+
+ public void dump(ProtoOutputStream proto, long fieldId, boolean full, long elapsedRealtimeMillis) {
+ final long token = proto.start(fieldId);
+
+ proto.write(JobStatusDumpProto.CALLING_UID, callingUid);
+ proto.write(JobStatusDumpProto.TAG, tag);
+ proto.write(JobStatusDumpProto.SOURCE_UID, getSourceUid());
+ proto.write(JobStatusDumpProto.SOURCE_USER_ID, getSourceUserId());
+ proto.write(JobStatusDumpProto.SOURCE_PACKAGE_NAME, getSourcePackageName());
+
+ if (full) {
+ final long jiToken = proto.start(JobStatusDumpProto.JOB_INFO);
+
+ job.getService().writeToProto(proto, JobStatusDumpProto.JobInfo.SERVICE);
+
+ proto.write(JobStatusDumpProto.JobInfo.IS_PERIODIC, job.isPeriodic());
+ proto.write(JobStatusDumpProto.JobInfo.PERIOD_INTERVAL_MS, job.getIntervalMillis());
+ proto.write(JobStatusDumpProto.JobInfo.PERIOD_FLEX_MS, job.getFlexMillis());
+
+ proto.write(JobStatusDumpProto.JobInfo.IS_PERSISTED, job.isPersisted());
+ proto.write(JobStatusDumpProto.JobInfo.PRIORITY, job.getPriority());
+ proto.write(JobStatusDumpProto.JobInfo.FLAGS, job.getFlags());
+
+ proto.write(JobStatusDumpProto.JobInfo.REQUIRES_CHARGING, job.isRequireCharging());
+ proto.write(JobStatusDumpProto.JobInfo.REQUIRES_BATTERY_NOT_LOW, job.isRequireBatteryNotLow());
+ proto.write(JobStatusDumpProto.JobInfo.REQUIRES_DEVICE_IDLE, job.isRequireDeviceIdle());
+
+ if (job.getTriggerContentUris() != null) {
+ for (int i = 0; i < job.getTriggerContentUris().length; i++) {
+ final long tcuToken = proto.start(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_URIS);
+ JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
+
+ proto.write(JobStatusDumpProto.JobInfo.TriggerContentUri.FLAGS, trig.getFlags());
+ Uri u = trig.getUri();
+ if (u != null) {
+ proto.write(JobStatusDumpProto.JobInfo.TriggerContentUri.URI, u.toString());
+ }
+
+ proto.end(tcuToken);
+ }
+ if (job.getTriggerContentUpdateDelay() >= 0) {
+ proto.write(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_UPDATE_DELAY_MS,
+ job.getTriggerContentUpdateDelay());
+ }
+ if (job.getTriggerContentMaxDelay() >= 0) {
+ proto.write(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_MAX_DELAY_MS,
+ job.getTriggerContentMaxDelay());
+ }
+ }
+ if (job.getExtras() != null && !job.getExtras().maybeIsEmpty()) {
+ job.getExtras().writeToProto(proto, JobStatusDumpProto.JobInfo.EXTRAS);
+ }
+ if (job.getTransientExtras() != null && !job.getTransientExtras().maybeIsEmpty()) {
+ job.getTransientExtras().writeToProto(proto, JobStatusDumpProto.JobInfo.TRANSIENT_EXTRAS);
+ }
+ if (job.getClipData() != null) {
+ job.getClipData().writeToProto(proto, JobStatusDumpProto.JobInfo.CLIP_DATA);
+ }
+ if (uriPerms != null) {
+ uriPerms.dump(proto, JobStatusDumpProto.JobInfo.GRANTED_URI_PERMISSIONS);
+ }
+ if (job.getRequiredNetwork() != null) {
+ job.getRequiredNetwork().writeToProto(proto, JobStatusDumpProto.JobInfo.REQUIRED_NETWORK);
+ }
+ if (totalNetworkBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+ proto.write(JobStatusDumpProto.JobInfo.TOTAL_NETWORK_BYTES, totalNetworkBytes);
+ }
+ proto.write(JobStatusDumpProto.JobInfo.MIN_LATENCY_MS, job.getMinLatencyMillis());
+ proto.write(JobStatusDumpProto.JobInfo.MAX_EXECUTION_DELAY_MS, job.getMaxExecutionDelayMillis());
+
+ final long bpToken = proto.start(JobStatusDumpProto.JobInfo.BACKOFF_POLICY);
+ proto.write(JobStatusDumpProto.JobInfo.Backoff.POLICY, job.getBackoffPolicy());
+ proto.write(JobStatusDumpProto.JobInfo.Backoff.INITIAL_BACKOFF_MS,
+ job.getInitialBackoffMillis());
+ proto.end(bpToken);
+
+ proto.write(JobStatusDumpProto.JobInfo.HAS_EARLY_CONSTRAINT, job.hasEarlyConstraint());
+ proto.write(JobStatusDumpProto.JobInfo.HAS_LATE_CONSTRAINT, job.hasLateConstraint());
+
+ proto.end(jiToken);
+ }
+
+ dumpConstraints(proto, JobStatusDumpProto.REQUIRED_CONSTRAINTS, requiredConstraints);
+ if (full) {
+ dumpConstraints(proto, JobStatusDumpProto.SATISFIED_CONSTRAINTS, satisfiedConstraints);
+ dumpConstraints(proto, JobStatusDumpProto.UNSATISFIED_CONSTRAINTS,
+ (requiredConstraints & ~satisfiedConstraints));
+ proto.write(JobStatusDumpProto.IS_DOZE_WHITELISTED, dozeWhitelisted);
+ }
+
+ // Tracking controllers
+ if ((trackingControllers&TRACKING_BATTERY) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_BATTERY);
+ }
+ if ((trackingControllers&TRACKING_CONNECTIVITY) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_CONNECTIVITY);
+ }
+ if ((trackingControllers&TRACKING_CONTENT) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_CONTENT);
+ }
+ if ((trackingControllers&TRACKING_IDLE) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_IDLE);
+ }
+ if ((trackingControllers&TRACKING_STORAGE) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_STORAGE);
+ }
+ if ((trackingControllers&TRACKING_TIME) != 0) {
+ proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+ JobStatusDumpProto.TRACKING_TIME);
+ }
+
+ if (changedAuthorities != null) {
+ for (int k = 0; k < changedAuthorities.size(); k++) {
+ proto.write(JobStatusDumpProto.CHANGED_AUTHORITIES, changedAuthorities.valueAt(k));
+ }
+ }
+ if (changedUris != null) {
+ for (int i = 0; i < changedUris.size(); i++) {
+ Uri u = changedUris.valueAt(i);
+ proto.write(JobStatusDumpProto.CHANGED_URIS, u.toString());
+ }
+ }
+
+ if (network != null) {
+ network.writeToProto(proto, JobStatusDumpProto.NETWORK);
+ }
+
+ if (pendingWork != null && pendingWork.size() > 0) {
+ for (int i = 0; i < pendingWork.size(); i++) {
+ dumpJobWorkItem(proto, JobStatusDumpProto.PENDING_WORK, pendingWork.get(i));
+ }
+ }
+ if (executingWork != null && executingWork.size() > 0) {
+ for (int i = 0; i < executingWork.size(); i++) {
+ dumpJobWorkItem(proto, JobStatusDumpProto.EXECUTING_WORK, executingWork.get(i));
+ }
+ }
+
+ proto.write(JobStatusDumpProto.STANDBY_BUCKET, standbyBucket);
+ proto.write(JobStatusDumpProto.ENQUEUE_DURATION_MS, elapsedRealtimeMillis - enqueueTime);
+ if (earliestRunTimeElapsedMillis == NO_EARLIEST_RUNTIME) {
+ proto.write(JobStatusDumpProto.TIME_UNTIL_EARLIEST_RUNTIME_MS, 0);
+ } else {
+ proto.write(JobStatusDumpProto.TIME_UNTIL_EARLIEST_RUNTIME_MS,
+ earliestRunTimeElapsedMillis - elapsedRealtimeMillis);
+ }
+ if (latestRunTimeElapsedMillis == NO_LATEST_RUNTIME) {
+ proto.write(JobStatusDumpProto.TIME_UNTIL_LATEST_RUNTIME_MS, 0);
+ } else {
+ proto.write(JobStatusDumpProto.TIME_UNTIL_LATEST_RUNTIME_MS,
+ latestRunTimeElapsedMillis - elapsedRealtimeMillis);
+ }
+
+ proto.write(JobStatusDumpProto.NUM_FAILURES, numFailures);
+ proto.write(JobStatusDumpProto.LAST_SUCCESSFUL_RUN_TIME, mLastSuccessfulRunTime);
+ proto.write(JobStatusDumpProto.LAST_FAILED_RUN_TIME, mLastFailedRunTime);
+
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 497faab..d3055e6 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -17,6 +17,7 @@
package com.android.server.job.controllers;
import android.content.Context;
+import android.util.proto.ProtoOutputStream;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
@@ -65,4 +66,6 @@
}
public abstract void dumpControllerStateLocked(PrintWriter pw, int filterUid);
+ public abstract void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+ int filterUid);
}
diff --git a/services/core/java/com/android/server/job/controllers/StorageController.java b/services/core/java/com/android/server/job/controllers/StorageController.java
index 84782f5..0519b63 100644
--- a/services/core/java/com/android/server/job/controllers/StorageController.java
+++ b/services/core/java/com/android/server/job/controllers/StorageController.java
@@ -25,10 +25,12 @@
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
import com.android.server.storage.DeviceStorageMonitorService;
import java.io.PrintWriter;
@@ -119,7 +121,7 @@
*/
private boolean mStorageLow;
/** Sequence number of last broadcast. */
- private int mLastBatterySeq = -1;
+ private int mLastStorageSeq = -1;
public StorageTracker() {
}
@@ -139,7 +141,7 @@
}
public int getSeq() {
- return mLastBatterySeq;
+ return mLastStorageSeq;
}
@Override
@@ -150,8 +152,8 @@
@VisibleForTesting
public void onReceiveInternal(Intent intent) {
final String action = intent.getAction();
- mLastBatterySeq = intent.getIntExtra(DeviceStorageMonitorService.EXTRA_SEQUENCE,
- mLastBatterySeq);
+ mLastStorageSeq = intent.getIntExtra(DeviceStorageMonitorService.EXTRA_SEQUENCE,
+ mLastStorageSeq);
if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
if (DEBUG) {
Slog.d(TAG, "Available storage too low to do work. @ "
@@ -190,4 +192,30 @@
pw.println();
}
}
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.STORAGE);
+
+ proto.write(StateControllerProto.StorageController.IS_STORAGE_NOT_LOW,
+ mStorageTracker.isStorageNotLow());
+ proto.write(StateControllerProto.StorageController.LAST_BROADCAST_SEQUENCE_NUMBER,
+ mStorageTracker.getSeq());
+
+ for (int i = 0; i < mTrackedTasks.size(); i++) {
+ final JobStatus js = mTrackedTasks.valueAt(i);
+ if (!js.shouldDump(filterUid)) {
+ continue;
+ }
+ final long jsToken = proto.start(StateControllerProto.StorageController.TRACKED_JOBS);
+ js.writeToShortProto(proto, StateControllerProto.StorageController.TrackedJob.INFO);
+ proto.write(StateControllerProto.StorageController.TrackedJob.SOURCE_UID,
+ js.getSourceUid());
+ proto.end(jsToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index cb9e43a..bbee0eb 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -25,9 +25,11 @@
import android.os.WorkSource;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
+import com.android.server.job.StateControllerProto;
import java.io.PrintWriter;
import java.util.Iterator;
@@ -331,7 +333,7 @@
public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
final long nowElapsed = sElapsedRealtimeClock.millis();
pw.print("Alarms: now=");
- pw.print(sElapsedRealtimeClock.millis());
+ pw.print(nowElapsed);
pw.println();
pw.print("Next delay alarm in ");
TimeUtils.formatDuration(mNextDelayExpiredElapsedMillis, nowElapsed, pw);
@@ -365,4 +367,40 @@
pw.println();
}
}
-}
\ No newline at end of file
+
+ @Override
+ public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+ final long token = proto.start(fieldId);
+ final long mToken = proto.start(StateControllerProto.TIME);
+
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ proto.write(StateControllerProto.TimeController.NOW_ELAPSED_REALTIME, nowElapsed);
+ proto.write(StateControllerProto.TimeController.TIME_UNTIL_NEXT_DELAY_ALARM_MS,
+ mNextDelayExpiredElapsedMillis - nowElapsed);
+ proto.write(StateControllerProto.TimeController.TIME_UNTIL_NEXT_DEADLINE_ALARM_MS,
+ mNextJobExpiredElapsedMillis - nowElapsed);
+
+ for (JobStatus ts : mTrackedJobs) {
+ if (!ts.shouldDump(filterUid)) {
+ continue;
+ }
+ final long tsToken = proto.start(StateControllerProto.TimeController.TRACKED_JOBS);
+ ts.writeToShortProto(proto, StateControllerProto.TimeController.TrackedJob.INFO);
+
+ proto.write(StateControllerProto.TimeController.TrackedJob.HAS_TIMING_DELAY_CONSTRAINT,
+ ts.hasTimingDelayConstraint());
+ proto.write(StateControllerProto.TimeController.TrackedJob.DELAY_TIME_REMAINING_MS,
+ ts.getEarliestRunTime() - nowElapsed);
+
+ proto.write(StateControllerProto.TimeController.TrackedJob.HAS_DEADLINE_CONSTRAINT,
+ ts.hasDeadlineConstraint());
+ proto.write(StateControllerProto.TimeController.TrackedJob.TIME_REMAINING_UNTIL_DEADLINE_MS,
+ ts.getLatestRunTimeElapsed() - nowElapsed);
+
+ proto.end(tsToken);
+ }
+
+ proto.end(mToken);
+ proto.end(token);
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1fa8da7..516828b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -912,8 +912,11 @@
}
private void notifySeparateProfileChallengeChanged(int userId) {
- LocalServices.getService(DevicePolicyManagerInternal.class)
- .reportSeparateProfileChallengeChanged(userId);
+ final DevicePolicyManagerInternal dpmi = LocalServices.getService(
+ DevicePolicyManagerInternal.class);
+ if (dpmi != null) {
+ dpmi.reportSeparateProfileChallengeChanged(userId);
+ }
}
@Override
@@ -1284,6 +1287,7 @@
fixateNewestUserKeyAuth(userId);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
notifyActivePasswordMetricsAvailable(null, userId);
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
return;
}
if (credential == null) {
@@ -1333,6 +1337,8 @@
.verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
+ userId);
// Refresh the auth token
doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
@@ -2031,6 +2037,11 @@
}
@Override
+ public void removeKey(@NonNull String alias) throws RemoteException {
+ mRecoverableKeyStoreManager.removeKey(alias);
+ }
+
+ @Override
public byte[] generateAndStoreKey(@NonNull String alias) throws RemoteException {
return mRecoverableKeyStoreManager.generateAndStoreKey(alias);
}
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 e385833..6079873 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -19,6 +19,7 @@
import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.security.recoverablekeystore.KeyDerivationParameters;
import android.security.recoverablekeystore.KeyEntryRecoveryData;
@@ -27,6 +28,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
@@ -69,6 +71,7 @@
private final int mUserId;
private final int mCredentialType;
private final String mCredential;
+ private final boolean mCredentialUpdated;
private final PlatformKeyManager.Factory mPlatformKeyManagerFactory;
private final RecoverySnapshotStorage mRecoverySnapshotStorage;
private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;
@@ -80,7 +83,8 @@
RecoverySnapshotListenersStorage recoverySnapshotListenersStorage,
int userId,
int credentialType,
- String credential
+ String credential,
+ boolean credentialUpdated
) throws NoSuchAlgorithmException, KeyStoreException, InsecureUserException {
return new KeySyncTask(
recoverableKeyStoreDb,
@@ -89,7 +93,8 @@
userId,
credentialType,
credential,
- () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb, userId));
+ credentialUpdated,
+ () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
}
/**
@@ -97,8 +102,9 @@
*
* @param recoverableKeyStoreDb Database where the keys are stored.
* @param userId The uid of the user whose profile has been unlocked.
- * @param credentialType The type of credential - i.e., pattern or password.
+ * @param credentialType The type of credential as defined in {@code LockPatternUtils}
* @param credential The credential, encoded as a {@link String}.
+ * @param credentialUpdated signals weather credentials were updated.
* @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user.
* This is a factory to enable unit testing, as otherwise it would be impossible to test
* without a screen unlock occurring!
@@ -111,12 +117,14 @@
int userId,
int credentialType,
String credential,
+ boolean credentialUpdated,
PlatformKeyManager.Factory platformKeyManagerFactory) {
mSnapshotListenersStorage = recoverySnapshotListenersStorage;
mRecoverableKeyStoreDb = recoverableKeyStoreDb;
mUserId = userId;
mCredentialType = credentialType;
mCredential = credential;
+ mCredentialUpdated = credentialUpdated;
mPlatformKeyManagerFactory = platformKeyManagerFactory;
mRecoverySnapshotStorage = snapshotStorage;
}
@@ -124,29 +132,44 @@
@Override
public void run() {
try {
- syncKeys();
+ // Only one task is active If user unlocks phone many times in a short time interval.
+ synchronized(KeySyncTask.class) {
+ syncKeys();
+ }
} catch (Exception e) {
Log.e(TAG, "Unexpected exception thrown during KeySyncTask", e);
}
}
private void syncKeys() {
- if (!isSyncPending()) {
+ if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ // Application keys for the user will not be available for sync.
+ Log.w(TAG, "Credentials are not set for user " + mUserId);
+ return;
+ }
+
+ List<Integer> recoveryAgents = mRecoverableKeyStoreDb.getRecoveryAgents(mUserId);
+ for (int uid : recoveryAgents) {
+ syncKeysForAgent(uid);
+ }
+ if (recoveryAgents.isEmpty()) {
+ Log.w(TAG, "No recovery agent initialized for user " + mUserId);
+ }
+ }
+
+ private void syncKeysForAgent(int recoveryAgentUid) {
+ if (!shoudCreateSnapshot(recoveryAgentUid)) {
Log.d(TAG, "Key sync not needed.");
return;
}
- int recoveryAgentUid = mRecoverableKeyStoreDb.getRecoveryAgentUid(mUserId);
- if (recoveryAgentUid == -1) {
- Log.w(TAG, "No recovery agent initialized for user " + mUserId);
- return;
- }
if (!mSnapshotListenersStorage.hasListener(recoveryAgentUid)) {
Log.w(TAG, "No pending intent registered for recovery agent " + recoveryAgentUid);
return;
}
- PublicKey publicKey = getVaultPublicKey();
+ PublicKey publicKey = mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId,
+ recoveryAgentUid);
if (publicKey == null) {
Log.w(TAG, "Not initialized for KeySync: no public key set. Cancelling task.");
return;
@@ -163,7 +186,7 @@
Map<String, SecretKey> rawKeys;
try {
- rawKeys = getKeysToSync();
+ rawKeys = getKeysToSync(recoveryAgentUid);
} catch (GeneralSecurityException e) {
Log.e(TAG, "Failed to load recoverable keys for sync", e);
return;
@@ -196,10 +219,19 @@
return;
}
- // TODO: where do we get counter_id from here?
+ Long counterId;
+ // counter id is generated exactly once for each credentials value.
+ if (mCredentialUpdated) {
+ counterId = generateAndStoreCounterId(recoveryAgentUid);
+ } else {
+ counterId = mRecoverableKeyStoreDb.getCounterId(mUserId, recoveryAgentUid);
+ if (counterId == null) {
+ counterId = generateAndStoreCounterId(recoveryAgentUid);
+ }
+ }
byte[] vaultParams = KeySyncUtils.packVaultParams(
publicKey,
- /*counterId=*/ 1,
+ counterId,
TRUSTED_HARDWARE_MAX_ATTEMPTS,
deviceId);
@@ -217,49 +249,77 @@
Log.e(TAG,"Could not encrypt with recovery key", e);
return;
}
-
+ // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
KeyStoreRecoveryMetadata metadata = new KeyStoreRecoveryMetadata(
/*userSecretType=*/ TYPE_LOCKSCREEN,
- /*lockScreenUiFormat=*/ mCredentialType,
- /*keyDerivationParameters=*/ KeyDerivationParameters.createSHA256Parameters(salt),
+ /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
+ /*keyDerivationParameters=*/ KeyDerivationParameters.createSha256Parameters(salt),
/*secret=*/ new byte[0]);
ArrayList<KeyStoreRecoveryMetadata> metadataList = new ArrayList<>();
metadataList.add(metadata);
- // TODO: implement snapshot version
- mRecoverySnapshotStorage.put(mUserId, new KeyStoreRecoveryData(
- /*snapshotVersion=*/ 1,
+ int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
+
+ // If application keys are not updated, snapshot will not be created on next unlock.
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
+
+ mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyStoreRecoveryData(
+ snapshotVersion,
/*recoveryMetadata=*/ metadataList,
/*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
/*encryptedRecoveryKeyblob=*/ encryptedRecoveryKey));
+
mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid);
}
- private PublicKey getVaultPublicKey() {
- return mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId);
+ @VisibleForTesting
+ int incrementSnapshotVersion(int recoveryAgentUid) {
+ Long snapshotVersion = mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid);
+ snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1;
+ mRecoverableKeyStoreDb.setSnapshotVersion(mUserId, recoveryAgentUid, snapshotVersion);
+
+ return snapshotVersion.intValue();
+ }
+
+ private long generateAndStoreCounterId(int recoveryAgentUid) {
+ long counter = new SecureRandom().nextLong();
+ mRecoverableKeyStoreDb.setCounterId(mUserId, recoveryAgentUid, counter);
+ return counter;
}
/**
* Returns all of the recoverable keys for the user.
*/
- private Map<String, SecretKey> getKeysToSync()
+ private Map<String, SecretKey> getKeysToSync(int recoveryAgentUid)
throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException {
PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance();
- PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey();
+ PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);
Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
- mUserId, decryptKey.getGenerationId());
+ mUserId, recoveryAgentUid, decryptKey.getGenerationId());
return WrappedKey.unwrapKeys(decryptKey, wrappedKeys);
}
/**
* Returns {@code true} if a sync is pending.
+ * @param recoveryAgentUid uid of the recovery agent.
*/
- private boolean isSyncPending() {
- // TODO: implement properly. For now just always syncing if the user has any recoverable
- // keys. We need to keep track of when the store's state actually changes.
- return !mRecoverableKeyStoreDb.getAllKeys(
- mUserId, mRecoverableKeyStoreDb.getPlatformKeyGenerationId(mUserId)).isEmpty();
+ private boolean shoudCreateSnapshot(int recoveryAgentUid) {
+ int[] types = mRecoverableKeyStoreDb.getRecoverySecretTypes(mUserId, recoveryAgentUid);
+ if (!ArrayUtils.contains(types, KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN)) {
+ // Only lockscreen type is supported.
+ // We will need to pass extra argument to KeySyncTask to support custom pass phrase.
+ return false;
+ }
+ if (mCredentialUpdated) {
+ // Sync credential if at least one snapshot was created.
+ if (mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid) != null) {
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, true);
+ return true;
+ }
+ }
+
+ return mRecoverableKeyStoreDb.getShouldCreateSnapshot(mUserId, recoveryAgentUid);
}
/**
@@ -295,7 +355,10 @@
* Returns {@code true} if {@code credential} looks like a pin.
*/
@VisibleForTesting
- static boolean isPin(@NonNull String credential) {
+ static boolean isPin(@Nullable String credential) {
+ if (credential == null) {
+ return false;
+ }
int length = credential.length();
for (int i = 0; i < length; i++) {
if (!Character.isDigit(credential.charAt(i))) {
@@ -342,7 +405,7 @@
for (String alias : encryptedApplicationKeys.keySet()) {
keyEntries.add(
new KeyEntryRecoveryData(
- alias.getBytes(StandardCharsets.UTF_8),
+ alias,
encryptedApplicationKeys.get(alias)));
}
return keyEntries;
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index a8b8361..7005de5 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -71,7 +71,6 @@
private final Context mContext;
private final KeyStoreProxy mKeyStore;
private final RecoverableKeyStoreDb mDatabase;
- private final int mUserId;
private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
@@ -80,34 +79,25 @@
* defined by {@code context}.
*
* @param context This should be the context of the RecoverableKeyStoreLoader service.
- * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @throws KeyStoreException if failed to initialize AndroidKeyStore.
* @throws NoSuchAlgorithmException if AES is unavailable - should never happen.
- * @throws InsecureUserException if the user does not have a lock screen set.
* @throws SecurityException if the caller does not have permission to write to /data/system.
*
* @hide
*/
- public static PlatformKeyManager getInstance(Context context, RecoverableKeyStoreDb database,
- int userId)
- throws KeyStoreException, NoSuchAlgorithmException, InsecureUserException {
- context = context.getApplicationContext();
- PlatformKeyManager keyManager = new PlatformKeyManager(
- userId,
- context,
+ public static PlatformKeyManager getInstance(Context context, RecoverableKeyStoreDb database)
+ throws KeyStoreException, NoSuchAlgorithmException {
+ return new PlatformKeyManager(
+ context.getApplicationContext(),
new KeyStoreProxyImpl(getAndLoadAndroidKeyStore()),
database);
- keyManager.init();
- return keyManager;
}
@VisibleForTesting
PlatformKeyManager(
- int userId,
Context context,
KeyStoreProxy keyStore,
RecoverableKeyStoreDb database) {
- mUserId = userId;
mKeyStore = keyStore;
mContext = context;
mDatabase = database;
@@ -118,67 +108,91 @@
* key has to be replaced. (e.g., because the user has removed and then re-added their lock
* screen). Returns -1 if no key has been generated yet.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
+ *
* @hide
*/
- public int getGenerationId() {
- return mDatabase.getPlatformKeyGenerationId(mUserId);
+ public int getGenerationId(int userId) {
+ return mDatabase.getPlatformKeyGenerationId(userId);
}
/**
* Returns {@code true} if the platform key is available. A platform key won't be available if
* the user has not set up a lock screen.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
+ *
* @hide
*/
- public boolean isAvailable() {
- return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(mUserId);
+ public boolean isAvailable(int userId) {
+ return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId);
}
/**
* Generates a new key and increments the generation ID. Should be invoked if the platform key
* is corrupted and needs to be rotated.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @throws NoSuchAlgorithmException if AES is unavailable - should never happen.
* @throws KeyStoreException if there is an error in AndroidKeyStore.
+ * @throws InsecureUserException if the user does not have a lock screen set.
*
* @hide
*/
- public void regenerate() throws NoSuchAlgorithmException, KeyStoreException {
- int nextId = getGenerationId() + 1;
- generateAndLoadKey(nextId);
+ public void regenerate(int userId)
+ throws NoSuchAlgorithmException, KeyStoreException, InsecureUserException {
+ if (!isAvailable(userId)) {
+ throw new InsecureUserException(String.format(
+ Locale.US, "%d does not have a lock screen set.", userId));
+ }
+
+ int generationId = getGenerationId(userId);
+ int nextId;
+ if (generationId == -1) {
+ nextId = 1;
+ } else {
+ nextId = generationId + 1;
+ }
+ generateAndLoadKey(userId, nextId);
}
/**
* Returns the platform key used for encryption.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @throws KeyStoreException if there was an AndroidKeyStore error.
* @throws UnrecoverableKeyException if the key could not be recovered.
* @throws NoSuchAlgorithmException if AES is unavailable - should never occur.
+ * @throws InsecureUserException if the user does not have a lock screen set.
*
* @hide
*/
- public PlatformEncryptionKey getEncryptKey()
- throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
- int generationId = getGenerationId();
+ public PlatformEncryptionKey getEncryptKey(int userId) throws KeyStoreException,
+ UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
+ init(userId);
+ int generationId = getGenerationId(userId);
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getEncryptAlias(generationId), /*password=*/ null);
+ getEncryptAlias(userId, generationId), /*password=*/ null);
return new PlatformEncryptionKey(generationId, key);
}
/**
* Returns the platform key used for decryption. Only works after a recent screen unlock.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @throws KeyStoreException if there was an AndroidKeyStore error.
* @throws UnrecoverableKeyException if the key could not be recovered.
* @throws NoSuchAlgorithmException if AES is unavailable - should never occur.
+ * @throws InsecureUserException if the user does not have a lock screen set.
*
* @hide
*/
- public PlatformDecryptionKey getDecryptKey()
- throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
- int generationId = getGenerationId();
+ public PlatformDecryptionKey getDecryptKey(int userId) throws KeyStoreException,
+ UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
+ init(userId);
+ int generationId = getGenerationId(userId);
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getDecryptAlias(generationId), /*password=*/ null);
+ getDecryptAlias(userId, generationId), /*password=*/ null);
return new PlatformDecryptionKey(generationId, key);
}
@@ -186,38 +200,36 @@
* Initializes the class. If there is no current platform key, and the user has a lock screen
* set, will create the platform key and set the generation ID.
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @throws KeyStoreException if there was an error in AndroidKeyStore.
* @throws NoSuchAlgorithmException if AES is unavailable - should never happen.
*
* @hide
*/
- public void init() throws KeyStoreException, NoSuchAlgorithmException, InsecureUserException {
- if (!isAvailable()) {
+ void init(int userId)
+ throws KeyStoreException, NoSuchAlgorithmException, InsecureUserException {
+ if (!isAvailable(userId)) {
throw new InsecureUserException(String.format(
- Locale.US, "%d does not have a lock screen set.", mUserId));
+ Locale.US, "%d does not have a lock screen set.", userId));
}
- int generationId = getGenerationId();
- if (isKeyLoaded(generationId)) {
+ int generationId = getGenerationId(userId);
+ if (isKeyLoaded(userId, generationId)) {
Log.i(TAG, String.format(
Locale.US, "Platform key generation %d exists already.", generationId));
return;
}
if (generationId == -1) {
Log.i(TAG, "Generating initial platform ID.");
+ generationId = 1;
} else {
Log.w(TAG, String.format(Locale.US, "Platform generation ID was %d but no "
+ "entry was present in AndroidKeyStore. Generating fresh key.", generationId));
- }
-
- if (generationId == -1) {
- generationId = 1;
- } else {
// Had to generate a fresh key, bump the generation id
generationId++;
}
- generateAndLoadKey(generationId);
+ generateAndLoadKey(userId, generationId);
}
/**
@@ -227,11 +239,12 @@
* <p>These IDs look as follows:
* {@code com.security.recoverablekeystore/platform/<user id>/<generation id>/encrypt}
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @param generationId The generation ID.
* @return The alias.
*/
- private String getEncryptAlias(int generationId) {
- return KEY_ALIAS_PREFIX + mUserId + "/" + generationId + "/" + ENCRYPT_KEY_ALIAS_SUFFIX;
+ private String getEncryptAlias(int userId, int generationId) {
+ return KEY_ALIAS_PREFIX + userId + "/" + generationId + "/" + ENCRYPT_KEY_ALIAS_SUFFIX;
}
/**
@@ -241,18 +254,19 @@
* <p>These IDs look as follows:
* {@code com.security.recoverablekeystore/platform/<user id>/<generation id>/decrypt}
*
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
* @param generationId The generation ID.
* @return The alias.
*/
- private String getDecryptAlias(int generationId) {
- return KEY_ALIAS_PREFIX + mUserId + "/" + generationId + "/" + DECRYPT_KEY_ALIAS_SUFFIX;
+ private String getDecryptAlias(int userId, int generationId) {
+ return KEY_ALIAS_PREFIX + userId + "/" + generationId + "/" + DECRYPT_KEY_ALIAS_SUFFIX;
}
/**
* Sets the current generation ID to {@code generationId}.
*/
- private void setGenerationId(int generationId) {
- mDatabase.setPlatformKeyGenerationId(mUserId, generationId);
+ private void setGenerationId(int userId, int generationId) {
+ mDatabase.setPlatformKeyGenerationId(userId, generationId);
}
/**
@@ -261,9 +275,9 @@
*
* @throws KeyStoreException if there was an error checking AndroidKeyStore.
*/
- private boolean isKeyLoaded(int generationId) throws KeyStoreException {
- return mKeyStore.containsAlias(getEncryptAlias(generationId))
- && mKeyStore.containsAlias(getDecryptAlias(generationId));
+ private boolean isKeyLoaded(int userId, int generationId) throws KeyStoreException {
+ return mKeyStore.containsAlias(getEncryptAlias(userId, generationId))
+ && mKeyStore.containsAlias(getDecryptAlias(userId, generationId));
}
/**
@@ -274,10 +288,10 @@
* available since API version 1.
* @throws KeyStoreException if there was an issue loading the keys into AndroidKeyStore.
*/
- private void generateAndLoadKey(int generationId)
+ private void generateAndLoadKey(int userId, int generationId)
throws NoSuchAlgorithmException, KeyStoreException {
- String encryptAlias = getEncryptAlias(generationId);
- String decryptAlias = getDecryptAlias(generationId);
+ String encryptAlias = getEncryptAlias(userId, generationId);
+ String decryptAlias = getDecryptAlias(userId, generationId);
SecretKey secretKey = generateAesKey();
mKeyStore.setEntry(
@@ -296,10 +310,10 @@
USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
- .setBoundToSpecificSecureUserId(mUserId)
+ .setBoundToSpecificSecureUserId(userId)
.build());
- setGenerationId(generationId);
+ setGenerationId(userId, generationId);
try {
secretKey.destroy();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
index 8c23d9b..2fe3f4e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
@@ -99,6 +99,7 @@
Locale.US, "Failed writing (%d, %s) to database.", uid, alias));
}
+ mDatabase.setShouldCreateSnapshot(userId, uid, true);
return key.getEncoded();
}
}
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 c73f852..a6f7766 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -16,6 +16,19 @@
package com.android.server.locksettings.recoverablekeystore;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
+ .ERROR_BAD_X509_CERTIFICATE;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader.ERROR_DATABASE_ERROR;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
+ .ERROR_DECRYPTION_FAILED;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader.ERROR_INSECURE_USER;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
+ .ERROR_KEYSTORE_INTERNAL_ERROR;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
+ .ERROR_NOT_YET_SUPPORTED;
+import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
+ .ERROR_UNEXPECTED_MISSING_ALGORITHM;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -45,6 +58,7 @@
import java.security.UnrecoverableKeyException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -63,12 +77,6 @@
public class RecoverableKeyStoreManager {
private static final String TAG = "RecoverableKeyStoreMgr";
- // TODO: move error codes to RecoverableKeyStoreLoader.
- private static int ERROR_INSECURE_USER = 1;
- private static int ERROR_KEYSTORE_INTERNAL_ERROR = 2;
- private static int ERROR_DATABASE_ERROR = 3;
- private static int ERROR_RECOVERY_SESSION_NOT_FOUND = 4;
-
private static RecoverableKeyStoreManager mInstance;
private final Context mContext;
@@ -78,22 +86,34 @@
private final RecoverySnapshotListenersStorage mListenersStorage;
private final RecoverableKeyGenerator mRecoverableKeyGenerator;
private final RecoverySnapshotStorage mSnapshotStorage;
+ private final PlatformKeyManager mPlatformKeyManager;
/**
* Returns a new or existing instance.
*
* @hide
*/
- public static synchronized RecoverableKeyStoreManager getInstance(Context mContext) {
+ public static synchronized RecoverableKeyStoreManager getInstance(Context context) {
if (mInstance == null) {
- RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(mContext);
+ RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context);
+ PlatformKeyManager platformKeyManager;
+ try {
+ platformKeyManager = PlatformKeyManager.getInstance(context, db);
+ } catch (NoSuchAlgorithmException e) {
+ // Impossible: all algorithms must be supported by AOSP
+ throw new RuntimeException(e);
+ } catch (KeyStoreException e) {
+ throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR, e.getMessage());
+ }
+
mInstance = new RecoverableKeyStoreManager(
- mContext.getApplicationContext(),
+ context.getApplicationContext(),
db,
new RecoverySessionStorage(),
Executors.newSingleThreadExecutor(),
new RecoverySnapshotStorage(),
- new RecoverySnapshotListenersStorage());
+ new RecoverySnapshotListenersStorage(),
+ platformKeyManager);
}
return mInstance;
}
@@ -105,18 +125,21 @@
RecoverySessionStorage recoverySessionStorage,
ExecutorService executorService,
RecoverySnapshotStorage snapshotStorage,
- RecoverySnapshotListenersStorage listenersStorage) {
+ RecoverySnapshotListenersStorage listenersStorage,
+ PlatformKeyManager platformKeyManager) {
mContext = context;
mDatabase = recoverableKeyStoreDb;
mRecoverySessionStorage = recoverySessionStorage;
mExecutorService = executorService;
mListenersStorage = listenersStorage;
mSnapshotStorage = snapshotStorage;
+ mPlatformKeyManager = platformKeyManager;
+
try {
mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase);
} catch (NoSuchAlgorithmException e) {
- // Impossible: all AOSP implementations must support AES.
- throw new RuntimeException(e);
+ Log.wtf(TAG, "AES keygen algorithm not available. AOSP must support this.", e);
+ throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
}
}
@@ -133,10 +156,11 @@
X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(signedPublicKeyList);
publicKey = kf.generatePublic(pkSpec);
} catch (NoSuchAlgorithmException e) {
- // Should never happen
- throw new RuntimeException(e);
+ Log.wtf(TAG, "EC algorithm not available. AOSP must support this.", e);
+ throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
} catch (InvalidKeySpecException e) {
- throw new RemoteException("Invalid public key for the recovery service");
+ throw new ServiceSpecificException(
+ ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 certificate.");
}
mDatabase.setRecoveryServicePublicKey(userId, Binder.getCallingUid(), publicKey);
}
@@ -150,8 +174,8 @@
public @NonNull KeyStoreRecoveryData getRecoveryData(@NonNull byte[] account)
throws RemoteException {
checkRecoverKeyStorePermission();
-
- KeyStoreRecoveryData snapshot = mSnapshotStorage.get(UserHandle.getCallingUserId());
+ int uid = Binder.getCallingUid();
+ KeyStoreRecoveryData snapshot = mSnapshotStorage.get(uid);
if (snapshot == null) {
throw new ServiceSpecificException(RecoverableKeyStoreLoader.ERROR_NO_SNAPSHOT_PENDING);
}
@@ -295,7 +319,26 @@
if (secrets.size() != 1) {
// TODO: support multiple secrets
- throw new RemoteException("Only a single KeyStoreRecoveryMetadata is supported");
+ throw new ServiceSpecificException(
+ ERROR_NOT_YET_SUPPORTED,
+ "Only a single KeyStoreRecoveryMetadata is supported");
+ }
+
+ PublicKey publicKey;
+ try {
+ publicKey = KeySyncUtils.deserializePublicKey(verifierPublicKey);
+ } catch (NoSuchAlgorithmException e) {
+ // Should never happen
+ throw new RuntimeException(e);
+ } catch (InvalidKeySpecException e) {
+ throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 key");
+ }
+ // The raw public key bytes contained in vaultParams must match the ones given in
+ // verifierPublicKey; otherwise, the user secret may be decrypted by a key that is not owned
+ // by the original recovery service.
+ if (!publicKeysMatch(publicKey, vaultParams)) {
+ throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE,
+ "The public keys given in verifierPublicKey and vaultParams do not match.");
}
byte[] keyClaimant = KeySyncUtils.generateKeyClaimant();
@@ -306,7 +349,6 @@
try {
byte[] thmKfHash = KeySyncUtils.calculateThmKfHash(kfHash);
- PublicKey publicKey = KeySyncUtils.deserializePublicKey(verifierPublicKey);
return KeySyncUtils.encryptRecoveryClaim(
publicKey,
vaultParams,
@@ -314,18 +356,10 @@
thmKfHash,
keyClaimant);
} catch (NoSuchAlgorithmException e) {
- // Should never happen: all the algorithms used are required by AOSP implementations.
- throw new RemoteException(
- "Missing required algorithm",
- e,
- /*enableSuppression=*/ true,
- /*writeableStackTrace=*/ true);
- } catch (InvalidKeySpecException | InvalidKeyException e) {
- throw new RemoteException(
- "Not a valid X509 key",
- e,
- /*enableSuppression=*/ true,
- /*writeableStackTrace=*/ true);
+ Log.wtf(TAG, "SecureBox algorithm missing. AOSP must support this.", e);
+ throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
+ } catch (InvalidKeyException e) {
+ throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE, e.getMessage());
}
}
@@ -334,7 +368,7 @@
* service.
*
* @param sessionId The session ID used to generate the claim. See
- * {@link #startRecoverySession(String, byte[], byte[], byte[], List, int)}.
+ * {@link #startRecoverySession(String, byte[], byte[], byte[], List)}.
* @param encryptedRecoveryKey The encrypted recovery key blob returned by the remote vault
* service.
* @param applicationKeys The encrypted key blobs returned by the remote vault service. These
@@ -378,11 +412,8 @@
int userId = UserHandle.getCallingUserId();
PlatformEncryptionKey encryptionKey;
-
try {
- PlatformKeyManager platformKeyManager = PlatformKeyManager.getInstance(
- mContext, mDatabase, userId);
- encryptionKey = platformKeyManager.getEncryptKey();
+ encryptionKey = mPlatformKeyManager.getEncryptKey(userId);
} catch (NoSuchAlgorithmException e) {
// Impossible: all algorithms must be supported by AOSP
throw new RuntimeException(e);
@@ -401,6 +432,16 @@
}
}
+ public void removeKey(@NonNull String alias) throws RemoteException {
+ int uid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
+
+ boolean wasRemoved = mDatabase.removeKey(uid, alias);
+ if (wasRemoved) {
+ mDatabase.setShouldCreateSnapshot(userId, uid, true);
+ }
+ }
+
private byte[] decryptRecoveryKey(
RecoverySessionStorage.Entry sessionEntry, byte[] encryptedClaimResponse)
throws RemoteException, ServiceSpecificException {
@@ -431,7 +472,7 @@
@NonNull List<KeyEntryRecoveryData> applicationKeys) throws RemoteException {
HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>();
for (KeyEntryRecoveryData applicationKey : applicationKeys) {
- String alias = new String(applicationKey.getAlias(), StandardCharsets.UTF_8);
+ String alias = applicationKey.getAlias();
byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
try {
@@ -439,18 +480,12 @@
KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial);
keyMaterialByAlias.put(alias, keyMaterial);
} catch (NoSuchAlgorithmException e) {
- // Should never happen: all the algorithms used are required by AOSP implementations
- throw new RemoteException(
- "Missing required algorithm",
- e,
- /*enableSuppression=*/ true,
- /*writeableStackTrace=*/ true);
+ Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e);
+ throw new ServiceSpecificException(
+ ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
} catch (InvalidKeyException | AEADBadTagException e) {
- throw new RemoteException(
- "Failed to recover key with alias '" + alias + "'",
- e,
- /*enableSuppression=*/ true,
- /*writeableStackTrace=*/ true);
+ throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
+ "Failed to recover key with alias '" + alias + "': " + e.getMessage());
}
}
return keyMaterialByAlias;
@@ -476,7 +511,8 @@
mListenersStorage,
userId,
storedHashType,
- credential));
+ credential,
+ /*credentialUpdated=*/ false));
} catch (NoSuchAlgorithmException e) {
Log.wtf(TAG, "Should never happen - algorithm unavailable for KeySync", e);
} catch (KeyStoreException e) {
@@ -486,12 +522,35 @@
}
}
- /** This function can only be used inside LockSettingsService. */
+ /**
+ * This function can only be used inside LockSettingsService.
+ * @param storedHashType from {@code CredentialHash}
+ * @param credential - unencrypted String
+ * @param userId for the user whose lock screen credentials were changed.
+ * @hide
+ */
public void lockScreenSecretChanged(
- @KeyStoreRecoveryMetadata.LockScreenUiFormat int type,
+ int storedHashType,
@Nullable String credential,
int userId) {
- throw new UnsupportedOperationException();
+ // So as not to block the critical path unlocking the phone, defer to another thread.
+ try {
+ mExecutorService.execute(KeySyncTask.newInstance(
+ mContext,
+ mDatabase,
+ mSnapshotStorage,
+ mListenersStorage,
+ userId,
+ storedHashType,
+ credential,
+ /*credentialUpdated=*/ true));
+ } catch (NoSuchAlgorithmException e) {
+ Log.wtf(TAG, "Should never happen - algorithm unavailable for KeySync", e);
+ } catch (KeyStoreException e) {
+ Log.e(TAG, "Key store error encountered during recoverable key sync", e);
+ } catch (InsecureUserException e) {
+ Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e);
+ }
}
private void checkRecoverKeyStorePermission() {
@@ -499,4 +558,9 @@
RecoverableKeyStoreLoader.PERMISSION_RECOVER_KEYSTORE,
"Caller " + Binder.getCallingUid() + " doesn't have RecoverKeyStore permission.");
}
+
+ private boolean publicKeysMatch(PublicKey publicKey, byte[] vaultParams) {
+ byte[] encodedPublicKey = SecureBox.encodePublicKey(publicKey);
+ return Arrays.equals(encodedPublicKey, Arrays.copyOf(vaultParams, encodedPublicKey.length));
+ }
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index 5ca5da4..c6f3ede 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -35,8 +35,10 @@
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringJoiner;
@@ -147,6 +149,19 @@
}
/**
+ * Removes key with {@code alias} for app with {@code uid}.
+ *
+ * @return {@code true} if deleted a row.
+ */
+ public boolean removeKey(int uid, String alias) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ String selection = KeysEntry.COLUMN_NAME_UID + " = ? AND " +
+ KeysEntry.COLUMN_NAME_ALIAS + " = ?";
+ String[] selectionArgs = { Integer.toString(uid), alias };
+ return db.delete(KeysEntry.TABLE_NAME, selection, selectionArgs) > 0;
+ }
+
+ /**
* Returns all statuses for keys {@code uid} and {@code platformKeyGenerationId}.
*
* @param uid of the application
@@ -207,16 +222,19 @@
}
/**
- * Returns all keys for the given {@code userId} and {@code platformKeyGenerationId}.
+ * Returns all keys for the given {@code userId} {@code recoveryAgentUid}
+ * and {@code platformKeyGenerationId}.
*
* @param userId User id of the profile to which all the keys are associated.
+ * @param recoveryAgentUid Uid of the recovery agent which will perform the sync
* @param platformKeyGenerationId The generation ID of the platform key that wrapped these keys.
* (i.e., this should be the most recent generation ID, as older platform keys are not
* usable.)
*
* @hide
*/
- public Map<String, WrappedKey> getAllKeys(int userId, int platformKeyGenerationId) {
+ public Map<String, WrappedKey> getAllKeys(int userId, int recoveryAgentUid,
+ int platformKeyGenerationId) {
SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
String[] projection = {
KeysEntry._ID,
@@ -226,9 +244,13 @@
KeysEntry.COLUMN_NAME_RECOVERY_STATUS};
String selection =
KeysEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + KeysEntry.COLUMN_NAME_UID + " = ? AND "
+ KeysEntry.COLUMN_NAME_GENERATION_ID + " = ?";
String[] selectionArguments = {
- Integer.toString(userId), Integer.toString(platformKeyGenerationId) };
+ Integer.toString(userId),
+ Integer.toString(recoveryAgentUid),
+ Integer.toString(platformKeyGenerationId)
+ };
try (
Cursor cursor = db.query(
@@ -328,9 +350,12 @@
}
/**
- * Returns the uid of the recovery agent for the given user, or -1 if none is set.
+ * Returns the list of recovery agents initialized for given {@code userId}
+ * @param userId The userId of the profile the application is running under.
+ * @return The list of recovery agents
+ * @hide
*/
- public int getRecoveryAgentUid(int userId) {
+ public @NonNull List<Integer> getRecoveryAgents(int userId) {
SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
String[] projection = { RecoveryServiceMetadataEntry.COLUMN_NAME_UID };
@@ -348,19 +373,20 @@
/*orderBy=*/ null)
) {
int count = cursor.getCount();
- if (count == 0) {
- return -1;
+ ArrayList<Integer> result = new ArrayList<>(count);
+ while (cursor.moveToNext()) {
+ int uid = cursor.getInt(
+ cursor.getColumnIndexOrThrow(RecoveryServiceMetadataEntry.COLUMN_NAME_UID));
+ result.add(uid);
}
- cursor.moveToFirst();
- return cursor.getInt(
- cursor.getColumnIndexOrThrow(RecoveryServiceMetadataEntry.COLUMN_NAME_UID));
+ return result;
}
}
/**
* Returns the public key of the recovery service.
*
- * @param userId The uid of the profile the application is running under.
+ * @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initializes the local recovery components.
*
* @hide
@@ -425,7 +451,7 @@
* If no secret types are set, recovery snapshot will not be created.
* See {@code KeyStoreRecoveryMetadata}
*
- * @param userId The uid of the profile the application is running under.
+ * @param userId The userId of the profile the application is running under.
* @param uid The uid of the application.
* @param secretTypes list of secret types
* @return The primary key of the updated row, or -1 if failed.
@@ -450,7 +476,7 @@
/**
* Returns the list of secret types used for end-to-end encryption.
*
- * @param userId The uid of the profile the application is running under.
+ * @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initialized the local recovery components.
* @return Secret types or empty array, if types were not set.
*
@@ -516,7 +542,7 @@
/**
* Returns the first (and only?) public key for {@code userId}.
*
- * @param userId The uid of the profile whose keys are to be synced.
+ * @param userId The userId of the profile whose keys are to be synced.
* @return The public key, or null if none exists.
*/
@Nullable
@@ -556,10 +582,40 @@
}
/**
+ * Updates the counterId
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application.
+ * @param counterId The counterId.
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+ public long setCounterId(int userId, int uid, long counterId) {
+ return setLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID, counterId);
+ }
+
+ /**
+ * Returns the counter id.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @return The counter id
+ *
+ * @hide
+ */
+ @Nullable
+ public Long getCounterId(int userId, int uid) {
+ return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID);
+ }
+
+
+ /**
* Updates the server parameters given by the application initializing the local recovery
* components.
*
- * @param userId The uid of the profile the application is running under.
+ * @param userId The userId of the profile the application is running under.
* @param uid The uid of the application.
* @param serverParameters The server parameters.
* @return The primary key of the inserted row, or -1 if failed.
@@ -567,24 +623,15 @@
* @hide
*/
public long setServerParameters(int userId, int uid, long serverParameters) {
- SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
- ContentValues values = new ContentValues();
- values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS, serverParameters);
- String selection =
- RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
- + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
- String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};
-
- ensureRecoveryServiceMetadataEntryExists(userId, uid);
- return db.update(
- RecoveryServiceMetadataEntry.TABLE_NAME, values, selection, selectionArguments);
+ return setLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS, serverParameters);
}
/**
* Returns the server paramters that was previously set by the application who initialized the
* local recovery service components.
*
- * @param userId The uid of the profile the application is running under.
+ * @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initialized the local recovery components.
* @return The server parameters that were previously set, or null if there's none.
*
@@ -592,27 +639,103 @@
*/
@Nullable
public Long getServerParameters(int userId, int uid) {
+ return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS);
+
+ }
+
+ /**
+ * Updates the snapshot version.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application.
+ * @param snapshotVersion The snapshot version
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+ public long setSnapshotVersion(int userId, int uid, long snapshotVersion) {
+ return setLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION, snapshotVersion);
+ }
+
+ /**
+ * Returns the snapshot version
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @return The server parameters that were previously set, or null if there's none.
+ *
+ * @hide
+ */
+ @Nullable
+ public Long getSnapshotVersion(int userId, int uid) {
+ return getLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION);
+ }
+
+ /**
+ * Updates the snapshot version.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application.
+ * @param pending The server parameters.
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+ public long setShouldCreateSnapshot(int userId, int uid, boolean pending) {
+ return setLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT, pending ? 1 : 0);
+ }
+
+ /**
+ * Returns {@code true} if new snapshot should be created.
+ * Returns {@code false} if the flag was never set.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @return snapshot outdated flag.
+ *
+ * @hide
+ */
+ public boolean getShouldCreateSnapshot(int userId, int uid) {
+ Long res = getLong(userId, uid,
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT);
+ return res != null && res != 0L;
+ }
+
+ /**
+ * Returns given long value from the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param key from {@code RecoveryServiceMetadataEntry}
+ * @return The value that were previously set, or null if there's none.
+ *
+ * @hide
+ */
+ private Long getLong(int userId, int uid, String key) {
SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
String[] projection = {
RecoveryServiceMetadataEntry._ID,
RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID,
RecoveryServiceMetadataEntry.COLUMN_NAME_UID,
- RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS};
+ key};
String selection =
RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};
try (
- Cursor cursor = db.query(
- RecoveryServiceMetadataEntry.TABLE_NAME,
- projection,
- selection,
- selectionArguments,
- /*groupBy=*/ null,
- /*having=*/ null,
- /*orderBy=*/ null)
+ Cursor cursor = db.query(
+ RecoveryServiceMetadataEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArguments,
+ /*groupBy=*/ null,
+ /*having=*/ null,
+ /*orderBy=*/ null)
) {
int count = cursor.getCount();
if (count == 0) {
@@ -621,13 +744,12 @@
if (count > 1) {
Log.wtf(TAG,
String.format(Locale.US,
- "%d deviceId entries found for userId=%d uid=%d. "
+ "%d entries found for userId=%d uid=%d. "
+ "Should only ever be 0 or 1.", count, userId, uid));
return null;
}
cursor.moveToFirst();
- int idx = cursor.getColumnIndexOrThrow(
- RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS);
+ int idx = cursor.getColumnIndexOrThrow(key);
if (cursor.isNull(idx)) {
return null;
} else {
@@ -637,6 +759,32 @@
}
/**
+ * Sets a long value in the database.
+ *
+ * @param userId The userId of the profile the application is running under.
+ * @param uid The uid of the application who initialized the local recovery components.
+ * @param key defined in {@code RecoveryServiceMetadataEntry}
+ * @param value new value.
+ * @return The primary key of the inserted row, or -1 if failed.
+ *
+ * @hide
+ */
+
+ private long setLong(int userId, int uid, String key, long value) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key, value);
+ String selection =
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
+ String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};
+
+ ensureRecoveryServiceMetadataEntryExists(userId, uid);
+ return db.update(
+ RecoveryServiceMetadataEntry.TABLE_NAME, values, selection, selectionArguments);
+ }
+
+ /**
* Creates an empty row in the recovery service metadata table if such a row doesn't exist for
* the given userId and uid, so db.update will succeed.
*/
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
index 8f773dd..597ae4c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
@@ -104,6 +104,15 @@
static final String COLUMN_NAME_UID = "uid";
/**
+ * Version of the latest recovery snapshot
+ */
+ static final String COLUMN_NAME_SNAPSHOT_VERSION = "snapshot_version";
+ /**
+ * Flag to generate new snapshot.
+ */
+ static final String COLUMN_NAME_SHOULD_CREATE_SNAPSHOT = "should_create_snapshot";
+
+ /**
* The public key of the recovery service.
*/
static final String COLUMN_NAME_PUBLIC_KEY = "public_key";
@@ -114,6 +123,11 @@
static final String COLUMN_NAME_SECRET_TYPES = "secret_types";
/**
+ * Locally generated random number.
+ */
+ static final String COLUMN_NAME_COUNTER_ID = "counter_id";
+
+ /**
* The server parameters of the recovery service.
*/
static final String COLUMN_NAME_SERVER_PARAMETERS = "server_parameters";
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
index 5b07f3e..6eb47ee 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
@@ -51,13 +51,16 @@
+ UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE,"
+ UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)";
- private static final String SQL_CREATE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY =
+ private static final String SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY =
"CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
+ RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER,"
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER,"
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT,"
+ + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER,"
+ RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS + " INTEGER,"
+ "UNIQUE("
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + ","
@@ -69,7 +72,7 @@
private static final String SQL_DELETE_USER_METADATA_ENTRY =
"DROP TABLE IF EXISTS " + UserMetadataEntry.TABLE_NAME;
- private static final String SQL_DELETE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY =
+ private static final String SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY =
"DROP TABLE IF EXISTS " + RecoveryServiceMetadataEntry.TABLE_NAME;
RecoverableKeyStoreDbHelper(Context context) {
@@ -80,14 +83,14 @@
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_KEYS_ENTRY);
db.execSQL(SQL_CREATE_USER_METADATA_ENTRY);
- db.execSQL(SQL_CREATE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY);
+ db.execSQL(SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_KEYS_ENTRY);
db.execSQL(SQL_DELETE_USER_METADATA_ENTRY);
- db.execSQL(SQL_DELETE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY);
+ db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY);
onCreate(db);
}
}
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 d1a1629..011b374 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
@@ -27,34 +27,34 @@
*
* <p>Recovery snapshots are generated after a successful screen unlock. They are only generated if
* the recoverable keystore has been mutated since the previous snapshot. This class stores only the
- * latest snapshot for each user.
+ * latest snapshot for each recovery agent.
*
* <p>This class is thread-safe. It is used both on the service thread and the
* {@link com.android.server.locksettings.recoverablekeystore.KeySyncTask} thread.
*/
public class RecoverySnapshotStorage {
@GuardedBy("this")
- private final SparseArray<KeyStoreRecoveryData> mSnapshotByUserId = new SparseArray<>();
+ private final SparseArray<KeyStoreRecoveryData> mSnapshotByUid = new SparseArray<>();
/**
- * Sets the latest {@code snapshot} for the user {@code userId}.
+ * Sets the latest {@code snapshot} for the recovery agent {@code uid}.
*/
- public synchronized void put(int userId, KeyStoreRecoveryData snapshot) {
- mSnapshotByUserId.put(userId, snapshot);
+ public synchronized void put(int uid, KeyStoreRecoveryData snapshot) {
+ mSnapshotByUid.put(uid, snapshot);
}
/**
- * Returns the latest snapshot for user {@code userId}, or null if none exists.
+ * Returns the latest snapshot for the recovery agent {@code uid}, or null if none exists.
*/
@Nullable
- public synchronized KeyStoreRecoveryData get(int userId) {
- return mSnapshotByUserId.get(userId);
+ public synchronized KeyStoreRecoveryData get(int uid) {
+ return mSnapshotByUid.get(uid);
}
/**
- * Removes any (if any) snapshot associated with user {@code userId}.
+ * Removes any (if any) snapshot associated with recovery agent {@code uid}.
*/
- public synchronized void remove(int userId) {
- mSnapshotByUserId.remove(userId);
+ public synchronized void remove(int uid) {
+ mSnapshotByUid.remove(uid);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3c47e85..ff9b2fd 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2793,6 +2793,11 @@
handleNetworkPoliciesUpdateAL(true);
}
}
+
+ final Intent intent = new Intent(SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+ mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2949,7 +2954,7 @@
if (state <= ActivityManager.PROCESS_STATE_TOP) {
fout.print(" (fg)");
} else {
- fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ fout.print(state <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
? " (fg svc)" : " (bg)");
}
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 f35e6ec..3bcc36f 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
@@ -53,9 +54,6 @@
private static final String TAG = NetworkWatchlistService.class.getSimpleName();
static final boolean DEBUG = false;
- private static final String PROPERTY_NETWORK_WATCHLIST_ENABLED =
- "ro.network_watchlist_enabled";
-
private static final int MAX_NUM_OF_WATCHLIST_DIGESTS = 10000;
public static class Lifecycle extends SystemService {
@@ -67,8 +65,10 @@
@Override
public void onStart() {
- if (!SystemProperties.getBoolean(PROPERTY_NETWORK_WATCHLIST_ENABLED, false)) {
+ if (Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.NETWORK_WATCHLIST_ENABLED, 0) == 0) {
// Watchlist service is disabled
+ Slog.i(TAG, "Network Watchlist service is disabled");
return;
}
mService = new NetworkWatchlistService(getContext());
@@ -77,11 +77,13 @@
@Override
public void onBootPhase(int phase) {
- if (!SystemProperties.getBoolean(PROPERTY_NETWORK_WATCHLIST_ENABLED, false)) {
- // Watchlist service is disabled
- return;
- }
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ if (Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.NETWORK_WATCHLIST_ENABLED, 0) == 0) {
+ // Watchlist service is disabled
+ Slog.i(TAG, "Network Watchlist service is disabled");
+ return;
+ }
try {
mService.initIpConnectivityMetrics();
mService.startWatchlistLogging();
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 7d64aed4..37e6ae9 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -251,23 +251,17 @@
for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
if (filter != null && !filter.matches(cmpt)) continue;
- final long cToken = proto.start(ManagedServicesProto.ENABLED);
- cmpt.toProto(proto);
- proto.end(cToken);
+ cmpt.writeToProto(proto, ManagedServicesProto.ENABLED);
}
for (ManagedServiceInfo info : mServices) {
if (filter != null && !filter.matches(info.component)) continue;
- final long lToken = proto.start(ManagedServicesProto.LIVE_SERVICES);
- info.toProto(proto, this);
- proto.end(lToken);
+ info.writeToProto(proto, ManagedServicesProto.LIVE_SERVICES, this);
}
for (ComponentName name : mSnoozingForCurrentProfiles) {
- final long cToken = proto.start(ManagedServicesProto.SNOOZED);
- name.toProto(proto);
- proto.end(cToken);
+ name.writeToProto(proto, ManagedServicesProto.SNOOZED);
}
}
@@ -1132,14 +1126,16 @@
.append(']').toString();
}
- public void toProto(ProtoOutputStream proto, ManagedServices host) {
- final long cToken = proto.start(ManagedServiceInfoProto.COMPONENT);
- component.toProto(proto);
- proto.end(cToken);
+ public void writeToProto(ProtoOutputStream proto, long fieldId, ManagedServices host) {
+ final long token = proto.start(fieldId);
+
+ component.writeToProto(proto, ManagedServiceInfoProto.COMPONENT);
proto.write(ManagedServiceInfoProto.USER_ID, userid);
proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName());
proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem);
proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host));
+
+ proto.end(token);
}
public boolean enabledAndUserMatches(int nid) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cf01400..575c44d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3376,9 +3376,7 @@
mListenersDisablingEffects.valueAt(i);
for (int j = 0; j < listeners.size(); j++) {
final ManagedServiceInfo listener = listeners.valueAt(i);
- listenersToken = proto.start(ListenersDisablingEffectsProto.LISTENERS);
- listener.toProto(proto, null);
- proto.end(listenersToken);
+ listener.writeToProto(proto, ListenersDisablingEffectsProto.LISTENERS, null);
}
proto.end(effectsToken);
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index a30e0639..fd9ffb2 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -278,7 +278,7 @@
// VisibleForTesting
public static String[] getExtraPeople(Bundle extras) {
- Object people = extras.get(Notification.EXTRA_PEOPLE);
+ Object people = extras.get(Notification.EXTRA_PEOPLE_LIST);
if (people instanceof String[]) {
return (String[]) people;
}
@@ -305,6 +305,16 @@
return array;
}
+ if (arrayList.get(0) instanceof Notification.Person) {
+ ArrayList<Notification.Person> list = (ArrayList<Notification.Person>) arrayList;
+ final int N = list.size();
+ String[] array = new String[N];
+ for (int i = 0; i < N; i++) {
+ array[i] = list.get(i).resolveToLegacyUri();
+ }
+ return array;
+ }
+
return null;
}
@@ -459,7 +469,9 @@
lookupResult = searchContacts(mContext, uri);
} else {
lookupResult = new LookupResult(); // invalid person for the cache
- Slog.w(TAG, "unsupported URI " + handle);
+ if (!"name".equals(uri.getScheme())) {
+ Slog.w(TAG, "unsupported URI " + handle);
+ }
}
if (lookupResult != null) {
synchronized (mPeopleCache) {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 7bab318..ebf6672 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -459,8 +459,7 @@
}
// Then, for the pinned set for each launcher, set the pin flag one by one.
- mShortcutUser.mService.getUserShortcutsLocked(getPackageUserId())
- .forAllLaunchers(launcherShortcuts -> {
+ mShortcutUser.forAllLaunchers(launcherShortcuts -> {
final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(
getPackageName(), getPackageUserId());
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 065eafd..d2bc6d2 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -396,7 +396,7 @@
private final long[] mDurationStats = new long[Stats.COUNT];
private static final int PROCESS_STATE_FOREGROUND_THRESHOLD =
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
static final int OPERATION_SET = 0;
static final int OPERATION_ADD = 1;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c3dce31..7d57566 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -63,6 +63,7 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -79,6 +80,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -241,8 +243,7 @@
private static final IBinder mUserRestriconToken = new Binder();
/**
- * User-related information that is used for persisting to flash. Only UserInfo is
- * directly exposed to other system apps.
+ * Internal non-parcelable wrapper for UserInfo that is not exposed to other system apps.
*/
@VisibleForTesting
static class UserData {
@@ -260,6 +261,12 @@
// Whether to perist the seed account information to be available after a boot
boolean persistSeedData;
+ /** Elapsed realtime since boot when the user started. */
+ long startRealtime;
+
+ /** Elapsed realtime since boot when the user was unlocked. */
+ long unlockRealtime;
+
void clearSeedAccountData() {
seedAccountName = null;
seedAccountType = null;
@@ -453,6 +460,37 @@
mUms.cleanupPartialUsers();
}
}
+
+ @Override
+ public void onStartUser(int userHandle) {
+ synchronized (mUms.mUsersLock) {
+ final UserData user = mUms.getUserDataLU(userHandle);
+ if (user != null) {
+ user.startRealtime = SystemClock.elapsedRealtime();
+ }
+ }
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ synchronized (mUms.mUsersLock) {
+ final UserData user = mUms.getUserDataLU(userHandle);
+ if (user != null) {
+ user.unlockRealtime = SystemClock.elapsedRealtime();
+ }
+ }
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ synchronized (mUms.mUsersLock) {
+ final UserData user = mUms.getUserDataLU(userHandle);
+ if (user != null) {
+ user.startRealtime = 0;
+ user.unlockRealtime = 0;
+ }
+ }
+ }
}
// TODO b/28848102 Add support for test dependencies injection
@@ -1057,6 +1095,29 @@
return mLocalService.isUserRunning(userId);
}
+ @Override
+ public long getUserStartRealtime() {
+ final int userId = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized (mUsersLock) {
+ final UserData user = getUserDataLU(userId);
+ if (user != null) {
+ return user.startRealtime;
+ }
+ return 0;
+ }
+ }
+
+ @Override
+ public long getUserUnlockRealtime() {
+ synchronized (mUsersLock) {
+ final UserData user = getUserDataLU(UserHandle.getUserId(Binder.getCallingUid()));
+ if (user != null) {
+ return user.unlockRealtime;
+ }
+ return 0;
+ }
+ }
+
private void checkManageOrInteractPermIfCallerInOtherProfileGroup(int userId, String name) {
int callingUserId = UserHandle.getCallingUserId();
if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
@@ -3484,6 +3545,7 @@
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
long now = System.currentTimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
StringBuilder sb = new StringBuilder();
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
@@ -3511,25 +3573,20 @@
}
pw.println(UserState.stateToString(state));
pw.print(" Created: ");
- if (userInfo.creationTime == 0) {
- pw.println("<unknown>");
- } else {
- sb.setLength(0);
- TimeUtils.formatDuration(now - userInfo.creationTime, sb);
- sb.append(" ago");
- pw.println(sb);
- }
+ dumpTimeAgo(pw, sb, now, userInfo.creationTime);
+
pw.print(" Last logged in: ");
- if (userInfo.lastLoggedInTime == 0) {
- pw.println("<unknown>");
- } else {
- sb.setLength(0);
- TimeUtils.formatDuration(now - userInfo.lastLoggedInTime, sb);
- sb.append(" ago");
- pw.println(sb);
- }
+ dumpTimeAgo(pw, sb, now, userInfo.lastLoggedInTime);
+
pw.print(" Last logged in fingerprint: ");
pw.println(userInfo.lastLoggedInFingerprint);
+
+ pw.print(" Start time: ");
+ dumpTimeAgo(pw, sb, nowRealtime, userData.startRealtime);
+
+ pw.print(" Unlock time: ");
+ dumpTimeAgo(pw, sb, nowRealtime, userData.unlockRealtime);
+
pw.print(" Has profile owner: ");
pw.println(mIsUserManaged.get(userId));
pw.println(" Restrictions:");
@@ -3593,6 +3650,17 @@
}
}
+ private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) {
+ if (time == 0) {
+ pw.println("<unknown>");
+ } else {
+ sb.setLength(0);
+ TimeUtils.formatDuration(nowTime - time, sb);
+ sb.append(" ago");
+ pw.println(sb);
+ }
+ }
+
final class MainHandler extends Handler {
@Override
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 6c8c9b2..ffc4731 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -5,3 +5,4 @@
per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com
per-file DefaultPermissionGrantPolicy.java = toddke@google.com
per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
+per-file DefaultPermissionGrantPolicy.java = patb@google.com
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 076c0e4..75d211b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -469,6 +469,7 @@
WindowState mNavigationBar = null;
boolean mHasNavigationBar = false;
boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
+ @NavigationBarPosition
int mNavigationBarPosition = NAV_BAR_BOTTOM;
int[] mNavigationBarHeightForRotationDefault = new int[4];
int[] mNavigationBarWidthForRotationDefault = new int[4];
@@ -4564,6 +4565,7 @@
dockFrame.top = displayFrames.mStable.top;
displayFrames.mContent.set(dockFrame);
displayFrames.mVoiceContent.set(dockFrame);
+ displayFrames.mCurrent.set(dockFrame);
if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
"dock=%s content=%s cur=%s", dockFrame.toString(),
@@ -4684,6 +4686,7 @@
return mNavigationBarController.checkHiddenLw();
}
+ @NavigationBarPosition
private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
if (mNavigationBarCanMove && displayWidth > displayHeight) {
if (displayRotation == Surface.ROTATION_270) {
@@ -7851,26 +7854,60 @@
return vis;
}
- private int updateLightNavigationBarLw(int vis, WindowState opaque,
- WindowState opaqueOrDimming) {
- final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
+ @VisibleForTesting
+ @Nullable
+ static WindowState chooseNavigationColorWindowLw(WindowState opaque,
+ WindowState opaqueOrDimming, WindowState imeWindow,
+ @NavigationBarPosition int navBarPosition) {
+ // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
+ // window can be navigation color window.
+ final boolean imeWindowCanNavColorWindow = imeWindow != null
+ && imeWindow.isVisibleLw()
+ && navBarPosition == NAV_BAR_BOTTOM
+ && (PolicyControl.getWindowFlags(imeWindow, null)
+ & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
- final WindowState navColorWin;
- if (imeWin != null && imeWin.isVisibleLw() && mNavigationBarPosition == NAV_BAR_BOTTOM) {
- navColorWin = imeWin;
- } else {
- navColorWin = opaqueOrDimming;
+ if (opaque != null && opaqueOrDimming == opaque) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
+ // unless IME window is also eligible, since currently the IME window is always show
+ // above the opaque fullscreen app window, regardless of the IME target window.
+ // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
+ return imeWindowCanNavColorWindow ? imeWindow : opaque;
}
+ if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
+ // No dimming window is involved. Determine the result only with the IME window.
+ return imeWindowCanNavColorWindow ? imeWindow : null;
+ }
+
+ if (!imeWindowCanNavColorWindow) {
+ // No IME window is involved. Determine the result only with opaqueOrDimming.
+ return opaqueOrDimming;
+ }
+
+ // The IME window and the dimming window are competing. Check if the dimming window can be
+ // IME target or not.
+ if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
+ // The IME window is above the dimming window.
+ return imeWindow;
+ } else {
+ // The dimming window is above the IME window.
+ return opaqueOrDimming;
+ }
+ }
+
+ @VisibleForTesting
+ static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
+ WindowState imeWindow, WindowState navColorWin) {
+
if (navColorWin != null) {
- if (navColorWin == opaque) {
- // If the top fullscreen-or-dimming window is also the top fullscreen, respect
- // its light flag.
+ if (navColorWin == imeWindow || navColorWin == opaque) {
+ // Respect the light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
& View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
- } else if (navColorWin.isDimming() || navColorWin == imeWin) {
- // Otherwise if it's dimming or it's the IME window, clear the light flag.
+ } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
+ // Clear the light flag for dimming window.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
}
}
@@ -8008,8 +8045,12 @@
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
+ final WindowState navColorWin = chooseNavigationColorWindowLw(
+ mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
+ mWindowManagerFuncs.getInputMethodWindowLw(), mNavigationBarPosition);
vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
- mTopFullscreenOpaqueOrDimmingWindowState);
+ mTopFullscreenOpaqueOrDimmingWindowState,
+ mWindowManagerFuncs.getInputMethodWindowLw(), navColorWin);
return vis;
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index cfe4088..40b656d 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -61,6 +61,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.Nullable;
@@ -141,6 +143,10 @@
int NAV_BAR_RIGHT = 1 << 1;
int NAV_BAR_BOTTOM = 1 << 2;
+ @Retention(SOURCE)
+ @IntDef({NAV_BAR_LEFT, NAV_BAR_RIGHT, NAV_BAR_BOTTOM})
+ @interface NavigationBarPosition {}
+
/**
* Pass this event to the user / app. To be returned from
* {@link #interceptKeyBeforeQueueing}.
@@ -1637,6 +1643,7 @@
* @see #NAV_BAR_RIGHT
* @see #NAV_BAR_BOTTOM
*/
+ @NavigationBarPosition
int getNavBarPosition();
/**
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index e5a23ea..2a153ec 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -209,10 +209,7 @@
try {
if (workSource != null) {
- final int N = workSource.size();
- for (int i=0; i<N; i++) {
- mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, workSource.get(i));
- }
+ mBatteryStats.noteLongPartialWakelockStartFromSource(tag, historyTag, workSource);
} else {
mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
}
@@ -230,10 +227,7 @@
try {
if (workSource != null) {
- final int N = workSource.size();
- for (int i=0; i<N; i++) {
- mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, workSource.get(i));
- }
+ mBatteryStats.noteLongPartialWakelockFinishFromSource(tag, historyTag, workSource);
} else {
mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 86b22bb..7273f62 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3140,7 +3140,8 @@
if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
- state.mProcState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+ state.mProcState >
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
disabled = true;
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 6fb345b..b986e04 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -21,8 +21,6 @@
import android.app.Dialog;
import android.app.IActivityManager;
import android.app.ProgressDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -114,7 +112,6 @@
private static String METRIC_AM = "shutdown_activity_manager";
private static String METRIC_PM = "shutdown_package_manager";
private static String METRIC_RADIOS = "shutdown_radios";
- private static String METRIC_BT = "shutdown_bt";
private static String METRIC_RADIO = "shutdown_radio";
private final Object mActionDoneSync = new Object();
@@ -408,7 +405,7 @@
/**
* Makes sure we handle the shutdown gracefully.
- * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
+ * Shuts off power regardless of radio state if the allotted time has passed.
*/
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog();
@@ -572,27 +569,10 @@
Thread t = new Thread() {
public void run() {
TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
- boolean bluetoothReadyForShutdown;
boolean radioOff;
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
- final IBluetoothManager bluetooth =
- IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
- BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
-
- try {
- bluetoothReadyForShutdown = bluetooth == null ||
- bluetooth.getState() == BluetoothAdapter.STATE_OFF;
- if (!bluetoothReadyForShutdown) {
- Log.w(TAG, "Disabling Bluetooth...");
- metricStarted(METRIC_BT);
- bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
try {
radioOff = phone == null || !phone.needMobileRadioShutdown();
@@ -606,7 +586,7 @@
radioOff = true;
}
- Log.i(TAG, "Waiting for Bluetooth and Radio...");
+ Log.i(TAG, "Waiting for Radio...");
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
@@ -617,25 +597,6 @@
sInstance.setRebootProgress(status, null);
}
- if (!bluetoothReadyForShutdown) {
- try {
- // BLE only mode can happen when BT is turned off
- // We will continue shutting down in such case
- bluetoothReadyForShutdown =
- bluetooth.getState() == BluetoothAdapter.STATE_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_ON;
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
- if (bluetoothReadyForShutdown) {
- Log.i(TAG, "Bluetooth turned off.");
- metricEnded(METRIC_BT);
- shutdownTimingsTraceLog
- .logDuration("ShutdownBt", TRON_METRICS.get(METRIC_BT));
- }
- }
if (!radioOff) {
try {
radioOff = !phone.needMobileRadioShutdown();
@@ -651,8 +612,8 @@
}
}
- if (radioOff && bluetoothReadyForShutdown) {
- Log.i(TAG, "Radio and Bluetooth shutdown complete.");
+ if (radioOff) {
+ Log.i(TAG, "Radio shutdown complete.");
done[0] = true;
break;
}
@@ -668,7 +629,7 @@
} catch (InterruptedException ex) {
}
if (!done[0]) {
- Log.w(TAG, "Timed out waiting for Radio and Bluetooth shutdown.");
+ Log.w(TAG, "Timed out waiting for Radio shutdown.");
}
}
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index a35383f..f7cc443 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -40,6 +40,7 @@
import android.os.storage.VolumeInfo;
import android.text.format.DateUtils;
import android.util.ArrayMap;
+import android.util.DataUnit;
import android.util.Slog;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -80,13 +81,13 @@
private static final int MSG_CHECK = 1;
- private static final long DEFAULT_LOG_DELTA_BYTES = 64 * TrafficStats.MB_IN_BYTES;
+ private static final long DEFAULT_LOG_DELTA_BYTES = DataUnit.MEBIBYTES.toBytes(64);
private static final long DEFAULT_CHECK_INTERVAL = DateUtils.MINUTE_IN_MILLIS;
// com.android.internal.R.string.low_internal_storage_view_text_no_boot
// hard codes 250MB in the message as the storage space required for the
// boot image.
- private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = 250 * TrafficStats.MB_IN_BYTES;
+ private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = DataUnit.MEBIBYTES.toBytes(250);
private NotificationManager mNotifManager;
diff --git a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
new file mode 100644
index 0000000..116fe7f
--- /dev/null
+++ b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.updates;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Telephony;
+import android.util.Log;
+
+public class CarrierIdInstallReceiver extends ConfigUpdateInstallReceiver {
+
+ public CarrierIdInstallReceiver() {
+ super("/data/misc/carrierid", "carrier_list.pb", "metadata/", "version");
+ }
+
+ @Override
+ protected void postInstall(Context context, Intent intent) {
+ ContentResolver resolver = context.getContentResolver();
+ resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.CONTENT_URI,
+ "update_db"), new ContentValues(), null, null);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 2ac7583..d4b437a 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -49,14 +49,17 @@
import static com.android.server.wm.proto.AppTransitionProto.APP_TRANSITION_STATE;
import static com.android.server.wm.proto.AppTransitionProto.LAST_USED_APP_TRANSITION;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Path;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
@@ -70,7 +73,10 @@
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.AppTransitionAnimationSpec;
+import android.view.DisplayListCanvas;
import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -391,6 +397,11 @@
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
}
+
+ boolean isNextAppTransitionOpenCrossProfileApps() {
+ return mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
+ }
+
/**
* @return true if and only if we are currently fetching app transition specs from the future
* passed into {@link #overridePendingAppTransitionMultiThumbFuture}
@@ -978,6 +989,43 @@
}
/**
+ * Creates an overlay with a background color and a thumbnail for the cross profile apps
+ * animation.
+ */
+ GraphicBuffer createCrossProfileAppsThumbnail(
+ @DrawableRes int thumbnailDrawableRes, Rect frame) {
+ final int width = frame.width();
+ final int height = frame.height();
+
+ final RenderNode node = RenderNode.create("CrossProfileAppsThumbnail", null);
+ node.setLeftTopRightBottom(0, 0, width, height);
+ node.setClipToBounds(false);
+
+ final DisplayListCanvas canvas = node.start(width, height);
+ canvas.drawColor(Color.argb(0.6f, 0, 0, 0));
+ final int thumbnailSize = mService.mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.cross_profile_apps_thumbnail_size);
+ final Drawable drawable = mService.mContext.getDrawable(thumbnailDrawableRes);
+ drawable.setBounds(
+ (width - thumbnailSize) / 2,
+ (height - thumbnailSize) / 2,
+ (width + thumbnailSize) / 2,
+ (height + thumbnailSize) / 2);
+ drawable.draw(canvas);
+ node.end(canvas);
+
+ return ThreadedRenderer.createHardwareBitmap(node, width, height)
+ .createGraphicBufferHandle();
+ }
+
+ Animation createCrossProfileAppsThumbnailAnimationLocked(Rect appRect) {
+ final Animation animation = loadAnimationRes(
+ "android", com.android.internal.R.anim.cross_profile_apps_thumbnail_enter);
+ return prepareThumbnailAnimationWithDuration(animation, appRect.width(),
+ appRect.height(), 0, null);
+ }
+
+ /**
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
* when a thumbnail is specified with the pending animation override.
*/
@@ -1624,9 +1672,10 @@
&& (transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_TASK_OPEN
|| transit == TRANSIT_TASK_TO_FRONT)) {
+
a = loadAnimationRes("android", enter
- ? com.android.internal.R.anim.activity_open_enter
- : com.android.internal.R.anim.activity_open_exit);
+ ? com.android.internal.R.anim.task_open_enter_cross_profile_apps
+ : com.android.internal.R.anim.task_open_exit);
Slog.v(TAG,
"applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:"
+ " anim=" + a + " transit=" + appTransitionToString(transit)
@@ -2007,6 +2056,8 @@
return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
+ case NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:
+ return "NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS";
default:
return "unknown type=" + mNextAppTransitionType;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index c16a531..db95634 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -20,12 +20,16 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
+import static com.android.server.wm.proto.AppWindowThumbnailProto.HEIGHT;
+import static com.android.server.wm.proto.AppWindowThumbnailProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.proto.AppWindowThumbnailProto.WIDTH;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Binder;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
@@ -49,7 +53,8 @@
AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
mAppToken = appToken;
- mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService);
+ mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
+ appToken.mService.mAnimator::addAfterPrepareSurfacesRunnable, appToken.mService);
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();
@@ -84,10 +89,14 @@
}
void startAnimation(Transaction t, Animation anim) {
+ startAnimation(t, anim, null /* position */);
+ }
+
+ void startAnimation(Transaction t, Animation anim, Point position) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked());
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
- new WindowAnimationSpec(anim, null /* position */,
+ new WindowAnimationSpec(anim, position,
mAppToken.mService.mAppTransition.canSkipFirstFrame()),
mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */);
}
@@ -109,6 +118,22 @@
mSurfaceControl.destroy();
}
+ /**
+ * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
+ * com.android.server.wm.proto.AppWindowThumbnailProto}.
+ *
+ * @param proto Stream to write the AppWindowThumbnail object to.
+ * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message.
+ * @hide
+ */
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(WIDTH, mWidth);
+ proto.write(HEIGHT, mHeight);
+ mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
+ proto.end(token);
+ }
+
@Override
public Transaction getPendingTransaction() {
return mAppToken.getPendingTransaction();
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index dcd88dd..f2098dc 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
@@ -31,6 +30,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
@@ -51,12 +51,32 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
+import static com.android.server.wm.proto.AppWindowTokenProto.ALL_DRAWN;
+import static com.android.server.wm.proto.AppWindowTokenProto.APP_STOPPED;
+import static com.android.server.wm.proto.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.proto.AppWindowTokenProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.proto.AppWindowTokenProto.FILLS_PARENT;
+import static com.android.server.wm.proto.AppWindowTokenProto.FROZEN_BOUNDS;
+import static com.android.server.wm.proto.AppWindowTokenProto.HIDDEN_REQUESTED;
+import static com.android.server.wm.proto.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.proto.AppWindowTokenProto.IS_REALLY_ANIMATING;
+import static com.android.server.wm.proto.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.proto.AppWindowTokenProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.proto.AppWindowTokenProto.LAST_SURFACE_SHOWING;
import static com.android.server.wm.proto.AppWindowTokenProto.NAME;
+import static com.android.server.wm.proto.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.proto.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.proto.AppWindowTokenProto.REMOVED;
+import static com.android.server.wm.proto.AppWindowTokenProto.REPORTED_DRAWN;
+import static com.android.server.wm.proto.AppWindowTokenProto.REPORTED_VISIBLE;
+import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_DISPLAYED;
+import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_MOVED;
+import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_WINDOW;
+import static com.android.server.wm.proto.AppWindowTokenProto.THUMBNAIL;
import static com.android.server.wm.proto.AppWindowTokenProto.WINDOW_TOKEN;
import android.annotation.CallSuper;
import android.app.Activity;
-import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
@@ -69,13 +89,14 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
-import android.view.SurfaceControl.Transaction;
-import android.view.animation.Animation;
import android.view.IApplicationToken;
import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
+import com.android.internal.R;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -649,8 +670,7 @@
boolean destroyedSomething = false;
// Copying to a different list as multiple children can be removed.
- // TODO: Not sure why this is needed.
- final LinkedList<WindowState> children = new LinkedList<>(mChildren);
+ final ArrayList<WindowState> children = new ArrayList<>(mChildren);
for (int i = children.size() - 1; i >= 0; i--) {
final WindowState win = children.get(i);
destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
@@ -1776,6 +1796,37 @@
mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
}
+ /**
+ * Attaches a surface with a thumbnail for the
+ * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
+ */
+ void attachCrossProfileAppsThumbnailAnimation() {
+ if (!isReallyAnimating()) {
+ return;
+ }
+ clearThumbnail();
+
+ final WindowState win = findMainWindow();
+ if (win == null) {
+ return;
+ }
+ final Rect frame = win.mFrame;
+ final int thumbnailDrawableRes = getTask().mUserId == mService.mCurrentUserId
+ ? R.drawable.ic_account_circle
+ : R.drawable.ic_corp_badge_no_background;
+ final GraphicBuffer thumbnail =
+ mService.mAppTransition
+ .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
+ if (thumbnail == null) {
+ return;
+ }
+ mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
+ final Animation animation =
+ mService.mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(win.mFrame);
+ mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
+ frame.top));
+ }
+
private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
@@ -1906,6 +1957,34 @@
final long token = proto.start(fieldId);
writeNameToProto(proto, NAME);
super.writeToProto(proto, WINDOW_TOKEN, trim);
+ proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
+ proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
+ proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
+ if (mThumbnail != null){
+ mThumbnail.writeToProto(proto, THUMBNAIL);
+ }
+ proto.write(FILLS_PARENT, mFillsParent);
+ proto.write(APP_STOPPED, mAppStopped);
+ proto.write(HIDDEN_REQUESTED, hiddenRequested);
+ proto.write(CLIENT_HIDDEN, mClientHidden);
+ proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
+ proto.write(REPORTED_DRAWN, reportedDrawn);
+ proto.write(REPORTED_VISIBLE, reportedVisible);
+ proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
+ proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
+ proto.write(ALL_DRAWN, allDrawn);
+ proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
+ proto.write(REMOVED, removed);
+ if (startingWindow != null){
+ startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
+ }
+ proto.write(STARTING_DISPLAYED, startingDisplayed);
+ proto.write(STARTING_MOVED, startingMoved);
+ proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+ mHiddenSetFromTransferredStartingWindow);
+ for (Rect bounds : mFrozenBounds) {
+ bounds.writeToProto(proto, FROZEN_BOUNDS);
+ }
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 63dfbc2..df468ac 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -62,6 +62,7 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
@@ -121,6 +122,7 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Matrix;
+import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
@@ -137,6 +139,7 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.InputDevice;
import android.view.MagnificationSpec;
@@ -158,6 +161,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -187,9 +191,10 @@
new NonAppWindowContainers("mBelowAppWindowsContainers", mService);
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
- // window containers together and move them in-sync if/when needed.
- private final NonAppWindowContainers mImeWindowsContainers =
- new NonAppWindowContainers("mImeWindowsContainers", mService);
+ // window containers together and move them in-sync if/when needed. We use a subclass of
+ // WindowContainer which is omitted from screen magnification, as the IME is never magnified.
+ private final NonMagnifiableWindowContainers mImeWindowsContainers =
+ new NonMagnifiableWindowContainers("mImeWindowsContainers", mService);
private WindowState mTmpWindow;
private WindowState mTmpWindow2;
@@ -207,6 +212,9 @@
int mInitialDisplayHeight = 0;
int mInitialDisplayDensity = 0;
+ DisplayCutout mInitialDisplayCutout;
+ DisplayCutout mDisplayCutoutOverride;
+
/**
* Overridden display size. Initialized with {@link #mInitialDisplayWidth}
* and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
@@ -1192,6 +1200,7 @@
mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
}
+ mDisplayInfo.displayCutout = calculateDisplayCutoutForCurrentRotation();
mDisplayInfo.getAppMetrics(mDisplayMetrics);
if (mDisplayScalingDisabled) {
mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
@@ -1213,6 +1222,18 @@
return mDisplayInfo;
}
+ DisplayCutout calculateDisplayCutoutForCurrentRotation() {
+ final DisplayCutout cutout = mInitialDisplayCutout;
+ if (cutout == null || cutout == DisplayCutout.NO_CUTOUT || mRotation == ROTATION_0) {
+ return cutout;
+ }
+ final Path bounds = cutout.getBounds().getBoundaryPath();
+ transformPhysicalToLogicalCoordinates(mRotation, mInitialDisplayWidth,
+ mInitialDisplayHeight, mTmpMatrix);
+ bounds.transform(mTmpMatrix);
+ return DisplayCutout.fromBounds(bounds);
+ }
+
/**
* Compute display configuration based on display properties and policy settings.
* Do not call if mDisplayReady == false.
@@ -1675,6 +1696,7 @@
mInitialDisplayWidth = mDisplayInfo.logicalWidth;
mInitialDisplayHeight = mDisplayInfo.logicalHeight;
mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
+ mInitialDisplayCutout = mDisplayInfo.displayCutout;
}
/**
@@ -1689,10 +1711,12 @@
final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
final int newDensity = mDisplayInfo.logicalDensityDpi;
+ final DisplayCutout newCutout = mDisplayInfo.displayCutout;
final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
|| mInitialDisplayHeight != newHeight
- || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi;
+ || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi
+ || !Objects.equals(mInitialDisplayCutout, newCutout);
if (displayMetricsChanged) {
// Check if display size or density is forced.
@@ -1709,6 +1733,7 @@
mInitialDisplayWidth = newWidth;
mInitialDisplayHeight = newHeight;
mInitialDisplayDensity = newDensity;
+ mInitialDisplayCutout = newCutout;
mService.reconfigureDisplayLocked(this);
}
}
@@ -3651,6 +3676,16 @@
}
}
+ private class NonMagnifiableWindowContainers extends NonAppWindowContainers {
+ NonMagnifiableWindowContainers(String name, WindowManagerService service) {
+ super(name, service);
+ }
+
+ @Override
+ void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
+ }
+ };
+
SurfaceControl.Builder makeSurface(SurfaceSession s) {
return mService.makeSurfaceBuilder(s)
.setParent(mWindowingLayer);
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index 0155712..bd06192 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.proto.DisplayFramesProto.STABLE_BOUNDS;
import android.annotation.NonNull;
+import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.proto.ProtoOutputStream;
@@ -100,9 +101,12 @@
/** During layout, the current screen borders along which input method windows are placed. */
public final Rect mDock = new Rect();
- /** Definition of the cutout */
+ /** The display cutout used for layout (after rotation and emulation) */
@NonNull public DisplayCutout mDisplayCutout = DisplayCutout.NO_CUTOUT;
+ /** The cutout as supplied by display info */
+ @NonNull private DisplayCutout mDisplayInfoCutout = DisplayCutout.NO_CUTOUT;
+
/**
* During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
*/
@@ -126,6 +130,8 @@
mRotation = info.rotation;
mDisplayInfoOverscan.set(
info.overscanLeft, info.overscanTop, info.overscanRight, info.overscanBottom);
+ mDisplayInfoCutout = info.displayCutout != null
+ ? info.displayCutout : DisplayCutout.NO_CUTOUT;
}
public void onBeginLayout(boolean emulateDisplayCutout, int statusBarHeight) {
@@ -166,12 +172,29 @@
mStable.set(mUnrestricted);
mStableFullscreen.set(mUnrestricted);
mCurrent.set(mUnrestricted);
- mDisplayCutout = DisplayCutout.NO_CUTOUT;
- mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
- Integer.MAX_VALUE, Integer.MAX_VALUE);
+ mDisplayCutout = mDisplayInfoCutout;
if (emulateDisplayCutout) {
setEmulatedDisplayCutout((int) (statusBarHeight * 0.8));
}
+ mDisplayCutout = mDisplayCutout.calculateRelativeTo(mOverscan);
+
+ mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
+ Integer.MAX_VALUE, Integer.MAX_VALUE);
+ if (!mDisplayCutout.isEmpty()) {
+ final DisplayCutout c = mDisplayCutout;
+ if (c.getSafeInsetLeft() > 0) {
+ mDisplayCutoutSafe.left = mRestrictedOverscan.left + c.getSafeInsetLeft();
+ }
+ if (c.getSafeInsetTop() > 0) {
+ mDisplayCutoutSafe.top = mRestrictedOverscan.top + c.getSafeInsetTop();
+ }
+ if (c.getSafeInsetRight() > 0) {
+ mDisplayCutoutSafe.right = mRestrictedOverscan.right - c.getSafeInsetRight();
+ }
+ if (c.getSafeInsetBottom() > 0) {
+ mDisplayCutoutSafe.bottom = mRestrictedOverscan.bottom - c.getSafeInsetBottom();
+ }
+ }
}
public int getInputMethodWindowVisibleHeight() {
@@ -194,8 +217,7 @@
new Point(height, (screenWidth - widthBottom) / 2),
new Point(height, (screenWidth + widthBottom) / 2),
new Point(0, (screenWidth + widthTop) / 2)
- )).calculateRelativeTo(mUnrestricted);
- mDisplayCutoutSafe.left = height;
+ ));
break;
case ROTATION_180:
mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
@@ -203,8 +225,7 @@
new Point((screenWidth - widthBottom) / 2, screenHeight - height),
new Point((screenWidth + widthBottom) / 2, screenHeight - height),
new Point((screenWidth + widthTop) / 2, screenHeight)
- )).calculateRelativeTo(mUnrestricted);
- mDisplayCutoutSafe.bottom = screenHeight - height;
+ ));
break;
case ROTATION_270:
mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
@@ -212,8 +233,7 @@
new Point(screenHeight - height, (screenWidth - widthBottom) / 2),
new Point(screenHeight - height, (screenWidth + widthBottom) / 2),
new Point(screenHeight, (screenWidth + widthTop) / 2)
- )).calculateRelativeTo(mUnrestricted);
- mDisplayCutoutSafe.right = screenHeight - height;
+ ));
break;
default:
mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
@@ -221,8 +241,7 @@
new Point((screenWidth - widthBottom) / 2, height),
new Point((screenWidth + widthBottom) / 2, height),
new Point((screenWidth + widthTop) / 2, 0)
- )).calculateRelativeTo(mUnrestricted);
- mDisplayCutoutSafe.top = height;
+ ));
break;
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 3a41eb0..dc62cc8 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -67,6 +67,9 @@
@VisibleForTesting
final ArrayMap<SurfaceControl, RunningAnimation> mRunningAnimations = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private boolean mAnimationStartDeferred;
+
SurfaceAnimationRunner() {
this(null /* callbackProvider */, null /* animatorFactory */, new Transaction());
}
@@ -86,13 +89,41 @@
: SfValueAnimator::new;
}
+ /**
+ * Defers starting of animations until {@link #continueStartingAnimations} is called. This
+ * method is NOT nestable.
+ *
+ * @see #continueStartingAnimations
+ */
+ void deferStartingAnimations() {
+ synchronized (mLock) {
+ mAnimationStartDeferred = true;
+ }
+ }
+
+ /**
+ * Continues starting of animations.
+ *
+ * @see #deferStartingAnimations
+ */
+ void continueStartingAnimations() {
+ synchronized (mLock) {
+ mAnimationStartDeferred = false;
+ if (!mPendingAnimations.isEmpty()) {
+ mChoreographer.postFrameCallback(this::startAnimations);
+ }
+ }
+ }
+
void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
Runnable finishCallback) {
synchronized (mLock) {
final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
finishCallback);
mPendingAnimations.put(animationLeash, runningAnim);
- mChoreographer.postFrameCallback(this::stepAnimation);
+ if (!mAnimationStartDeferred) {
+ mChoreographer.postFrameCallback(this::startAnimations);
+ }
// Some animations (e.g. move animations) require the initial transform to be applied
// immediately.
@@ -185,7 +216,7 @@
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
- private void stepAnimation(long frameTimeNanos) {
+ private void startAnimations(long frameTimeNanos) {
synchronized (mLock) {
startPendingAnimationsLocked();
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index a32e711..10f1c3a 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -19,17 +19,21 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.SurfaceAnimatorProto.ANIMATION_ADAPTER;
+import static com.android.server.wm.proto.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
+import static com.android.server.wm.proto.SurfaceAnimatorProto.LEASH;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.util.ArrayMap;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.function.Consumer;
/**
* A class that can run animations on objects that have a set of child surfaces. We do this by
@@ -55,16 +59,20 @@
/**
* @param animatable The object to animate.
* @param animationFinishedCallback Callback to invoke when an animation has finished running.
+ * @param addAfterPrepareSurfaces Consumer that takes a runnable and executes it after preparing
+ * surfaces in WM. Can be implemented differently during testing.
*/
SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
- WindowManagerService service) {
+ Consumer<Runnable> addAfterPrepareSurfaces, WindowManagerService service) {
mAnimatable = animatable;
mService = service;
mAnimationFinishedCallback = animationFinishedCallback;
- mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
+ mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback,
+ addAfterPrepareSurfaces);
}
- private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback) {
+ private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback,
+ Consumer<Runnable> addAfterPrepareSurfaces) {
return anim -> {
synchronized (mService.mWindowMap) {
final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
@@ -80,7 +88,7 @@
// reparents the surface onto the leash is executed already. Otherwise this may be
// executed first, leading to surface loss, as the reparent operations wouldn't
// be in order.
- mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
+ addAfterPrepareSurfaces.accept(() -> {
if (anim != mAnimation) {
// Callback was from another animation - ignore.
return;
@@ -304,6 +312,24 @@
return leash;
}
+ /**
+ * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
+ * com.android.server.wm.proto.SurfaceAnimatorProto}.
+ *
+ * @param proto Stream to write the SurfaceAnimator object to.
+ * @param fieldId Field Id of the SurfaceAnimator as defined in the parent message.
+ * @hide
+ */
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(ANIMATION_ADAPTER, mAnimation != null ? mAnimation.toString() : "null");
+ if (mLeash != null){
+ mLeash.writeToProto(proto, LEASH);
+ }
+ proto.write(ANIMATION_START_DELAYED, mAnimationStartDelayed);
+ proto.end(token);
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
pw.print(" mLeash="); pw.println(mLeash);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3c96ca1..0628436 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -22,13 +22,13 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.EMPTY;
-
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.proto.TaskProto.APP_WINDOW_TOKENS;
import static com.android.server.wm.proto.TaskProto.BOUNDS;
+import static com.android.server.wm.proto.TaskProto.DEFER_REMOVAL;
import static com.android.server.wm.proto.TaskProto.FILLS_PARENT;
import static com.android.server.wm.proto.TaskProto.ID;
import static com.android.server.wm.proto.TaskProto.TEMP_INSET_BOUNDS;
@@ -670,6 +670,7 @@
proto.write(FILLS_PARENT, matchParentBounds());
getBounds().writeToProto(proto, BOUNDS);
mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS);
+ proto.write(DEFER_REMOVAL, mDeferRemoval);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eb8eae1..7024fb1 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
-import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -31,20 +31,24 @@
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
-
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.StackProto.ADJUSTED_BOUNDS;
+import static com.android.server.wm.proto.StackProto.ADJUSTED_FOR_IME;
+import static com.android.server.wm.proto.StackProto.ADJUST_DIVIDER_AMOUNT;
+import static com.android.server.wm.proto.StackProto.ADJUST_IME_AMOUNT;
import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
import static com.android.server.wm.proto.StackProto.BOUNDS;
+import static com.android.server.wm.proto.StackProto.DEFER_REMOVAL;
import static com.android.server.wm.proto.StackProto.FILLS_PARENT;
import static com.android.server.wm.proto.StackProto.ID;
+import static com.android.server.wm.proto.StackProto.MINIMIZE_AMOUNT;
import static com.android.server.wm.proto.StackProto.TASKS;
import static com.android.server.wm.proto.StackProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.content.res.Configuration;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.RemoteException;
@@ -146,7 +150,6 @@
* For {@link #prepareSurfaces}.
*/
final Rect mTmpDimBoundsRect = new Rect();
- private final Point mLastSurfaceSize = new Point();
TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
super(service);
@@ -716,10 +719,11 @@
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
+ super.onConfigurationChanged(newParentConfig);
+
// Only need to update surface size here since the super method will handle updating
// surface position.
updateSurfaceSize(getPendingTransaction());
- super.onConfigurationChanged(newParentConfig);
final int windowingMode = getWindowingMode();
if (mDisplayContent == null || prevWindowingMode == windowingMode) {
@@ -745,13 +749,7 @@
}
final Rect stackBounds = getBounds();
- final int width = stackBounds.width();
- final int height = stackBounds.height();
- if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
- return;
- }
- transaction.setSize(mSurfaceControl, width, height);
- mLastSurfaceSize.set(width, height);
+ transaction.setSize(mSurfaceControl, stackBounds.width(), stackBounds.height());
}
@Override
@@ -1315,6 +1313,12 @@
proto.write(FILLS_PARENT, matchParentBounds());
getRawBounds().writeToProto(proto, BOUNDS);
proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown);
+ proto.write(DEFER_REMOVAL, mDeferRemoval);
+ proto.write(MINIMIZE_AMOUNT, mMinimizeAmount);
+ proto.write(ADJUSTED_FOR_IME, mAdjustedForIme);
+ proto.write(ADJUST_IME_AMOUNT, mAdjustImeAmount);
+ proto.write(ADJUST_DIVIDER_AMOUNT, mAdjustDividerAmount);
+ mAdjustedBounds.writeToProto(proto, ADJUSTED_BOUNDS);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 031b57b..0863ee9 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -89,7 +89,10 @@
if (mStackClipMode == STACK_CLIP_NONE) {
t.setWindowCrop(leash, tmp.transformation.getClipRect());
} else if (mStackClipMode == STACK_CLIP_AFTER_ANIM) {
- t.setFinalCrop(leash, mStackBounds);
+ mTmpRect.set(mStackBounds);
+ // Offset stack bounds to stack position so the final crop is in screen space.
+ mTmpRect.offsetTo(mPosition.x, mPosition.y);
+ t.setFinalCrop(leash, mTmpRect);
t.setWindowCrop(leash, tmp.transformation.getClipRect());
} else {
mTmpRect.set(mStackBounds);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 7295873..3efd6ac 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -47,7 +47,6 @@
final WindowManagerService mService;
final Context mContext;
final WindowManagerPolicy mPolicy;
- private final WindowSurfacePlacer mWindowPlacerLocked;
/** Is any window animating? */
private boolean mAnimating;
@@ -74,7 +73,7 @@
SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
- boolean mInitialized = false;
+ private boolean mInitialized = false;
// When set to true the animator will go over all windows after an animation frame is posted and
// check if some got replaced and can be removed.
@@ -98,7 +97,6 @@
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
- mWindowPlacerLocked = service.mWindowPlacerLocked;
AnimationThread.getHandler().runWithScissors(
() -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
@@ -241,7 +239,7 @@
}
if (hasPendingLayoutChanges || doRequest) {
- mWindowPlacerLocked.requestTraversal();
+ mService.mWindowPlacerLocked.requestTraversal();
}
final boolean rootAnimating = mService.mRoot.isSelfOrChildAnimating();
@@ -254,7 +252,7 @@
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
if (!rootAnimating && mLastRootAnimating) {
- mWindowPlacerLocked.requestTraversal();
+ mService.mWindowPlacerLocked.requestTraversal();
mService.mTaskSnapshotController.setPersisterPaused(false);
Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index af31410..c267c70 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -19,26 +19,26 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.SurfaceControl.Transaction;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.proto.WindowContainerProto.CONFIGURATION_CONTAINER;
import static com.android.server.wm.proto.WindowContainerProto.ORIENTATION;
+import static com.android.server.wm.proto.WindowContainerProto.SURFACE_ANIMATOR;
import static com.android.server.wm.proto.WindowContainerProto.VISIBLE;
-import static android.view.SurfaceControl.Transaction;
import android.annotation.CallSuper;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
+import android.util.Pools;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.MagnificationSpec;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
-import android.util.Pools;
-
-import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.wm.SurfaceAnimator.Animatable;
@@ -95,7 +95,6 @@
protected final WindowManagerService mService;
private final Point mTmpPos = new Point();
- protected final Point mLastSurfacePosition = new Point();
/** Total number of elements in this subtree, including our own hierarchy element. */
private int mTreeWeight = 1;
@@ -103,7 +102,8 @@
WindowContainer(WindowManagerService service) {
mService = service;
mPendingTransaction = service.mTransactionFactory.make();
- mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
+ mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
+ service.mAnimator::addAfterPrepareSurfacesRunnable, service);
}
@Override
@@ -971,6 +971,7 @@
super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
proto.write(ORIENTATION, mOrientation);
proto.write(VISIBLE, isVisible());
+ mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
proto.end(token);
}
@@ -1178,12 +1179,7 @@
}
getRelativePosition(mTmpPos);
- if (mTmpPos.equals(mLastSurfacePosition)) {
- return;
- }
-
transaction.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
- mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
for (int i = mChildren.size() - 1; i >= 0; i--) {
mChildren.get(i).updateSurfacePosition(transaction);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0a2ffbc..fcc9988 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -928,7 +928,6 @@
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
installLock(this, INDEX_WINDOW);
- mRoot = new RootWindowContainer(this);
mContext = context;
mHaveInputMethods = haveInputMethods;
mAllowBootMessages = showBootMsgs;
@@ -952,8 +951,11 @@
mDisplaySettings = new DisplaySettings();
mDisplaySettings.readSettingsLocked();
- mWindowPlacerLocked = new WindowSurfacePlacer(this);
mPolicy = policy;
+ mAnimator = new WindowAnimator(this);
+ mRoot = new RootWindowContainer(this);
+
+ mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);
@@ -1051,7 +1053,6 @@
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
- mAnimator = new WindowAnimator(this);
mSurfaceAnimationRunner = new SurfaceAnimationRunner();
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
@@ -5326,6 +5327,25 @@
reconfigureDisplayLocked(displayContent);
}
+ @Override
+ public void startWindowTrace(){
+ try {
+ mWindowTracing.startTrace(null /* printwriter */);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void stopWindowTrace(){
+ mWindowTracing.stopTrace(null /* printwriter */);
+ }
+
+ @Override
+ public boolean isWindowTraceEnabled() {
+ return mWindowTracing.isEnabled();
+ }
+
// -------------------------------------------------------------
// Internals
// -------------------------------------------------------------
@@ -5874,6 +5894,7 @@
* the screen is.
* @see WindowManagerPolicy#getNavBarPosition()
*/
+ @WindowManagerPolicy.NavigationBarPosition
public int getNavBarPosition() {
synchronized (mWindowMap) {
// Perform layout if it was scheduled before to make sure that we get correct nav bar
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index fcbc802..b3809dd 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1543,10 +1543,13 @@
@Override
public boolean canAffectSystemUiFlags() {
final boolean translucent = mAttrs.alpha == 0.0f;
+ if (translucent) {
+ return false;
+ }
if (mAppToken == null) {
final boolean shown = mWinAnimator.getShown();
final boolean exiting = mAnimatingExit || mDestroying;
- return shown && !exiting && !translucent;
+ return shown && !exiting;
} else {
return !mAppToken.isHidden();
}
@@ -2664,8 +2667,11 @@
boolean destroySurface(boolean cleanupOnResume, boolean appStopped) {
boolean destroyedSomething = false;
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = mChildren.get(i);
+
+ // Copying to a different list as multiple children can be removed.
+ final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
+ for (int i = childWindows.size() - 1; i >= 0; --i) {
+ final WindowState c = childWindows.get(i);
destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped);
}
@@ -3923,8 +3929,7 @@
if (!mChildren.isEmpty()) {
// Copying to a different list as multiple children can be removed.
- // TODO: Not sure if we really need to copy this into a different list.
- final LinkedList<WindowState> childWindows = new LinkedList(mChildren);
+ final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
for (int i = childWindows.size() - 1; i >= 0; i--) {
childWindows.get(i).onExitAnimationDone();
}
@@ -4482,7 +4487,6 @@
// Leash is now responsible for position, so set our position to 0.
t.setPosition(mSurfaceControl, 0, 0);
- mLastSurfacePosition.set(0, 0);
}
@Override
@@ -4498,9 +4502,8 @@
}
transformFrameToSurfacePosition(mFrame.left, mFrame.top, mSurfacePosition);
- if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) {
+ if (!mSurfaceAnimator.hasLeash()) {
t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y);
- mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
}
}
@@ -4578,7 +4581,8 @@
private MoveAnimationSpec(int fromX, int fromY, int toX, int toY) {
final Animation anim = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.window_move_from_decor);
- mDuration = anim.computeDurationHint();
+ mDuration = (long)
+ (anim.computeDurationHint() * mService.getWindowAnimationScaleLocked());
mInterpolator = anim.getInterpolator();
mFrom.set(fromX, fromY);
mTo.set(toX, toY);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index bdab9c7..a512fdf 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManagerInternal.APP_TRANSITION_SNAPSHOT;
import static android.app.ActivityManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
@@ -43,28 +44,19 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
-import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
-import android.content.res.Configuration;
-import android.graphics.GraphicBuffer;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Binder;
import android.os.Debug;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseIntArray;
import android.view.Display;
-import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
@@ -349,21 +341,28 @@
animLp = null;
}
- processApplicationsAnimatingInPlace(transit);
+ final int layoutRedo;
+ mService.mSurfaceAnimationRunner.deferStartingAnimations();
+ try {
+ processApplicationsAnimatingInPlace(transit);
- mTmpLayerAndToken.token = null;
- handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken);
- final AppWindowToken topClosingApp = mTmpLayerAndToken.token;
- final AppWindowToken topOpeningApp = handleOpeningApps(transit, animLp, voiceInteraction);
+ mTmpLayerAndToken.token = null;
+ handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken);
+ final AppWindowToken topClosingApp = mTmpLayerAndToken.token;
+ final AppWindowToken topOpeningApp = handleOpeningApps(transit, animLp,
+ voiceInteraction);
- mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp);
+ mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp);
- final int flags = mService.mAppTransition.getTransitFlags();
- int layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp,
- topClosingApp, mService.mOpeningApps, mService.mClosingApps);
- handleNonAppWindowsInTransition(transit, flags);
- mService.mAppTransition.postAnimationCallback();
- mService.mAppTransition.clear();
+ final int flags = mService.mAppTransition.getTransitFlags();
+ layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp,
+ topClosingApp, mService.mOpeningApps, mService.mClosingApps);
+ handleNonAppWindowsInTransition(transit, flags);
+ mService.mAppTransition.postAnimationCallback();
+ mService.mAppTransition.clear();
+ } finally {
+ mService.mSurfaceAnimationRunner.continueStartingAnimations();
+ }
mService.mTaskSnapshotController.onTransitionStarting();
@@ -407,7 +406,6 @@
}
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
-
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
mService.openSurfaceTransaction();
@@ -428,6 +426,8 @@
}
if (mService.mAppTransition.isNextAppTransitionThumbnailUp()) {
wtoken.attachThumbnailAnimation();
+ } else if (mService.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
+ wtoken.attachCrossProfileAppsThumbnailAnimation();
}
}
return topOpeningApp;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index bad9bf5..172efdc 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -16,11 +16,7 @@
package com.android.server.wm;
-import android.annotation.CallSuper;
-import android.util.proto.ProtoOutputStream;
-import java.util.Comparator;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -28,15 +24,20 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.proto.WindowTokenProto.HASH_CODE;
+import static com.android.server.wm.proto.WindowTokenProto.HIDDEN;
+import static com.android.server.wm.proto.WindowTokenProto.PAUSED;
+import static com.android.server.wm.proto.WindowTokenProto.WAITING_TO_SHOW;
import static com.android.server.wm.proto.WindowTokenProto.WINDOWS;
import static com.android.server.wm.proto.WindowTokenProto.WINDOW_CONTAINER;
+import android.annotation.CallSuper;
import android.os.Debug;
import android.os.IBinder;
import android.util.Slog;
-import android.view.SurfaceControl;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
+import java.util.Comparator;
/**
* Container of a set of related windows in the window manager. Often this is an AppWindowToken,
@@ -276,6 +277,9 @@
final WindowState w = mChildren.get(i);
w.writeToProto(proto, WINDOWS, trim);
}
+ proto.write(HIDDEN, mHidden);
+ proto.write(WAITING_TO_SHOW, waitingToShow);
+ proto.write(PAUSED, paused);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index c858b19..a299781 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -29,6 +29,7 @@
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
+import android.annotation.Nullable;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -62,7 +63,7 @@
mTraceFile = file;
}
- void startTrace(PrintWriter pw) throws IOException {
+ void startTrace(@Nullable PrintWriter pw) throws IOException {
if (IS_USER){
logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
return;
@@ -81,13 +82,15 @@
}
}
- private void logAndPrintln(PrintWriter pw, String msg) {
+ private void logAndPrintln(@Nullable PrintWriter pw, String msg) {
Log.i(TAG, msg);
- pw.println(msg);
- pw.flush();
+ if (pw != null) {
+ pw.println(msg);
+ pw.flush();
+ }
}
- void stopTrace(PrintWriter pw) {
+ void stopTrace(@Nullable PrintWriter pw) {
if (IS_USER){
logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
return;
diff --git a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java
new file mode 100644
index 0000000..09d7b5d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java
@@ -0,0 +1,62 @@
+/*
+ * 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.wm.utils;
+
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.annotation.Dimension;
+import android.graphics.Matrix;
+import android.view.Surface.Rotation;
+
+public class CoordinateTransforms {
+
+ private CoordinateTransforms() {
+ }
+
+ /**
+ * Sets a matrix such that given a rotation, it transforms physical display
+ * coordinates to that rotation's logical coordinates.
+ *
+ * @param rotation the rotation to which the matrix should transform
+ * @param out the matrix to be set
+ */
+ public static void transformPhysicalToLogicalCoordinates(@Rotation int rotation,
+ @Dimension int physicalWidth, @Dimension int physicalHeight, Matrix out) {
+ switch (rotation) {
+ case ROTATION_0:
+ out.reset();
+ break;
+ case ROTATION_90:
+ out.setRotate(270);
+ out.postTranslate(0, physicalWidth);
+ break;
+ case ROTATION_180:
+ out.setRotate(180);
+ out.postTranslate(physicalWidth, physicalHeight);
+ break;
+ case ROTATION_270:
+ out.setRotate(90);
+ out.postTranslate(physicalHeight, 0);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown rotation: " + rotation);
+ }
+ }
+}
diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
index 79f482c..62bab07 100644
--- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp
+++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
@@ -94,6 +94,9 @@
j_str = env->NewString((jchar*)byteBuffer, numUSC2Bytes/2);
free(byteBuffer);
}
+
+ usb_device_close(device);
+
return j_str;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index c1e95eb..29ac4ce 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -64,7 +64,7 @@
public void setSystemSetting(ComponentName who, String setting, String value){}
- public void transferOwner(ComponentName admin, ComponentName target, PersistableBundle bundle) {}
+ public void transferOwnership(ComponentName admin, ComponentName target, PersistableBundle bundle) {}
public boolean generateKeyPair(ComponentName who, String callerPackage, String algorithm,
ParcelableKeyGenParameterSpec keySpec, int idAttestationFlags,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 11fce4d..3592fc0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -20,6 +20,7 @@
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.USER_OP_SUCCESS;
+import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
@@ -154,7 +155,6 @@
import android.provider.ContactsInternal;
import android.provider.Settings;
import android.provider.Settings.Global;
-import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@@ -6506,13 +6506,36 @@
}
}
- synchronized void sendDeviceOwnerCommand(String action, Bundle extras) {
- Intent intent = new Intent(action);
- intent.setComponent(mOwners.getDeviceOwnerComponent());
+ void sendDeviceOwnerCommand(String action, Bundle extras) {
+ int deviceOwnerUserId;
+ ComponentName deviceOwnerComponent;
+ synchronized (this) {
+ deviceOwnerUserId = mOwners.getDeviceOwnerUserId();
+ deviceOwnerComponent = mOwners.getDeviceOwnerComponent();
+ }
+ sendActiveAdminCommand(action, extras, deviceOwnerUserId,
+ deviceOwnerComponent);
+ }
+
+ private void sendProfileOwnerCommand(String action, Bundle extras, int userHandle) {
+ sendActiveAdminCommand(action, extras, userHandle,
+ mOwners.getProfileOwnerComponent(userHandle));
+ }
+
+ private void sendActiveAdminCommand(String action, Bundle extras,
+ int userHandle, ComponentName receiverComponent) {
+ final Intent intent = new Intent(action);
+ intent.setComponent(receiverComponent);
if (extras != null) {
intent.putExtras(extras);
}
- mContext.sendBroadcastAsUser(intent, UserHandle.of(mOwners.getDeviceOwnerUserId()));
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(userHandle));
+ }
+
+ private void sendOwnerChangedBroadcast(String broadcast, int userId) {
+ final Intent intent = new Intent(broadcast)
+ .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
}
private synchronized String getDeviceOwnerRemoteBugreportUri() {
@@ -6890,10 +6913,7 @@
ident = mInjector.binderClearCallingIdentity();
try {
// TODO Send to system too?
- mContext.sendBroadcastAsUser(
- new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED)
- .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
- UserHandle.of(userId));
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -7044,9 +7064,8 @@
try {
clearDeviceOwnerLocked(admin, deviceOwnerUserId);
removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
- Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- mContext.sendBroadcastAsUser(intent, UserHandle.of(deviceOwnerUserId));
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
+ deviceOwnerUserId);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -7131,6 +7150,8 @@
ensureUnknownSourcesRestrictionForProfileOwnerLocked(userHandle, admin,
true /* newOwner */);
}
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
+ userHandle);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
@@ -7159,6 +7180,8 @@
try {
clearProfileOwnerLocked(admin, userId);
removeActiveAdminLocked(who, userId);
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
+ userId);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -7190,13 +7213,8 @@
return;
}
- final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!isUserAffiliatedWithDeviceLocked(userId)) {
- throw new SecurityException("Admin " + who +
- " is neither the device owner or affiliated user's profile owner.");
- }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long token = mInjector.binderClearCallingIdentity();
try {
mLockPatternUtils.setDeviceOwnerInfo(info != null ? info.toString() : null);
@@ -9663,6 +9681,9 @@
" is neither the device owner or affiliated user's profile owner.");
}
}
+ if (isManagedProfile(userId)) {
+ throw new SecurityException("Managed profile cannot disable keyguard");
+ }
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -9689,6 +9710,9 @@
throw new SecurityException("Admin " + who +
" is neither the device owner or affiliated user's profile owner.");
}
+ if (isManagedProfile(userId)) {
+ throw new SecurityException("Managed profile cannot disable status bar");
+ }
DevicePolicyData policy = getUserData(userId);
if (policy.mStatusBarDisabled != disabled) {
boolean isLockTaskMode = false;
@@ -11846,9 +11870,9 @@
}
//TODO: Add callback information to the javadoc once it is completed.
- //TODO: Make transferOwner atomic.
+ //TODO: Make transferOwnership atomic.
@Override
- public void transferOwner(ComponentName admin, ComponentName target, PersistableBundle bundle) {
+ public void transferOwnership(ComponentName admin, ComponentName target, PersistableBundle bundle) {
if (!mHasFeature) {
return;
}
@@ -11876,13 +11900,12 @@
final long id = mInjector.binderClearCallingIdentity();
try {
- //STOPSHIP add support for COMP, edge cases when device is rebooted/work mode off,
- //transfer callbacks and broadcast
+ //STOPSHIP add support for COMP, edge cases when device is rebooted/work mode off
synchronized (this) {
if (isProfileOwner(admin, callingUserId)) {
- transferProfileOwnerLocked(admin, target, callingUserId);
+ transferProfileOwnerLocked(admin, target, callingUserId, bundle);
} else if (isDeviceOwner(admin, callingUserId)) {
- transferDeviceOwnerLocked(admin, target, callingUserId);
+ transferDeviceOwnerLocked(admin, target, callingUserId, bundle);
}
}
} finally {
@@ -11894,24 +11917,40 @@
* Transfers the profile owner for user with id profileOwnerUserId from admin to target.
*/
private void transferProfileOwnerLocked(ComponentName admin, ComponentName target,
- int profileOwnerUserId) {
+ int profileOwnerUserId, PersistableBundle bundle) {
transferActiveAdminUncheckedLocked(target, admin, profileOwnerUserId);
mOwners.transferProfileOwner(target, profileOwnerUserId);
Slog.i(LOG_TAG, "Profile owner set: " + target + " on user " + profileOwnerUserId);
mOwners.writeProfileOwner(profileOwnerUserId);
mDeviceAdminServiceController.startServiceForOwner(
target.getPackageName(), profileOwnerUserId, "transfer-profile-owner");
+ sendProfileOwnerCommand(DeviceAdminReceiver.ACTION_TRANSFER_OWNERSHIP_COMPLETE,
+ getTransferOwnerAdminExtras(bundle), profileOwnerUserId);
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
+ profileOwnerUserId);
}
/**
* Transfers the device owner for user with id userId from admin to target.
*/
- private void transferDeviceOwnerLocked(ComponentName admin, ComponentName target, int userId) {
+ private void transferDeviceOwnerLocked(ComponentName admin, ComponentName target, int userId,
+ PersistableBundle bundle) {
transferActiveAdminUncheckedLocked(target, admin, userId);
mOwners.transferDeviceOwner(target);
Slog.i(LOG_TAG, "Device owner set: " + target + " on user " + userId);
mOwners.writeDeviceOwner();
mDeviceAdminServiceController.startServiceForOwner(
target.getPackageName(), userId, "transfer-device-owner");
+ sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_TRANSFER_OWNERSHIP_COMPLETE,
+ getTransferOwnerAdminExtras(bundle));
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
+ }
+
+ private Bundle getTransferOwnerAdminExtras(PersistableBundle bundle) {
+ Bundle extras = new Bundle();
+ if (bundle != null) {
+ extras.putParcelable(EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE, bundle);
+ }
+ return extras;
}
}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 31a1abb..7d9736e 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -38,6 +38,7 @@
import android.net.metrics.ApfStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
@@ -56,7 +57,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
@@ -247,7 +247,7 @@
private final ApfCapabilities mApfCapabilities;
private final IpClient.Callback mIpClientCallback;
- private final NetworkInterface mNetworkInterface;
+ private final InterfaceParams mInterfaceParams;
private final IpConnectivityLog mMetricsLog;
@VisibleForTesting
@@ -269,11 +269,11 @@
private int mIPv4PrefixLength;
@VisibleForTesting
- ApfFilter(ApfConfiguration config, NetworkInterface networkInterface,
+ ApfFilter(ApfConfiguration config, InterfaceParams ifParams,
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
mApfCapabilities = config.apfCapabilities;
mIpClientCallback = ipClientCallback;
- mNetworkInterface = networkInterface;
+ mInterfaceParams = ifParams;
mMulticastFilter = config.multicastFilter;
mDrop802_3Frames = config.ieee802_3Filter;
@@ -287,7 +287,7 @@
}
private void log(String s) {
- Log.d(TAG, "(" + mNetworkInterface.getName() + "): " + s);
+ Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
}
@GuardedBy("this")
@@ -332,14 +332,14 @@
void maybeStartFilter() {
FileDescriptor socket;
try {
- mHardwareAddress = mNetworkInterface.getHardwareAddress();
+ mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
synchronized(this) {
// Install basic filters
installNewProgramLocked();
}
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
- mNetworkInterface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress(
+ (short) ETH_P_IPV6, mInterfaceParams.index);
Os.bind(socket, addr);
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
} catch(SocketException|ErrnoException e) {
@@ -1168,10 +1168,10 @@
* filtering using APF programs.
*/
public static ApfFilter maybeCreate(ApfConfiguration config,
- NetworkInterface networkInterface, IpClient.Callback ipClientCallback) {
- if (config == null) return null;
+ InterfaceParams ifParams, IpClient.Callback ipClientCallback) {
+ if (config == null || ifParams == null) return null;
ApfCapabilities apfCapabilities = config.apfCapabilities;
- if (apfCapabilities == null || networkInterface == null) return null;
+ if (apfCapabilities == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
@@ -1186,7 +1186,7 @@
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
- return new ApfFilter(config, networkInterface, ipClientCallback, new IpConnectivityLog());
+ return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog());
}
public synchronized void shutdown() {
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index ed78175..a956cef 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -34,6 +34,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
+import android.net.util.InterfaceParams;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -50,7 +51,6 @@
import java.io.IOException;
import java.lang.Thread;
import java.net.Inet4Address;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -187,7 +187,8 @@
private final String mIfaceName;
private boolean mRegisteredForPreDhcpNotification;
- private NetworkInterface mIface;
+ private InterfaceParams mIface;
+ // TODO: MacAddress-ify more of this class hierarchy.
private byte[] mHwAddr;
private PacketSocketAddress mInterfaceBroadcastAddr;
private int mTransactionId;
@@ -221,8 +222,9 @@
return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
}
+ // TODO: Take an InterfaceParams instance instead of an interface name String.
private DhcpClient(Context context, StateMachine controller, String iface) {
- super(TAG);
+ super(TAG, controller.getHandler());
mContext = context;
mController = controller;
@@ -262,23 +264,23 @@
}
public static DhcpClient makeDhcpClient(
- Context context, StateMachine controller, String intf) {
- DhcpClient client = new DhcpClient(context, controller, intf);
+ Context context, StateMachine controller, InterfaceParams ifParams) {
+ DhcpClient client = new DhcpClient(context, controller, ifParams.name);
+ client.mIface = ifParams;
client.start();
return client;
}
private boolean initInterface() {
- try {
- mIface = NetworkInterface.getByName(mIfaceName);
- mHwAddr = mIface.getHardwareAddress();
- mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(),
- DhcpPacket.ETHER_BROADCAST);
- return true;
- } catch(SocketException | NullPointerException e) {
- Log.e(TAG, "Can't determine ifindex or MAC address for " + mIfaceName, e);
+ if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName);
+ if (mIface == null) {
+ Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName);
return false;
}
+
+ mHwAddr = mIface.macAddr.toByteArray();
+ mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST);
+ return true;
}
private void startNewTransaction() {
@@ -293,7 +295,7 @@
private boolean initPacketSocket() {
try {
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index);
Os.bind(mPacketSock, addr);
NetworkUtils.attachDhcpFilter(mPacketSock);
} catch(SocketException|ErrnoException e) {
diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
index 6cf4fa9a..e6ddbbc 100644
--- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java
+++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
@@ -21,6 +21,7 @@
import android.net.NetworkUtils;
import android.net.util.PacketReader;
import android.net.util.ConnectivityPacketSummary;
+import android.net.util.InterfaceParams;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.Os;
@@ -35,7 +36,6 @@
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.io.IOException;
-import java.net.NetworkInterface;
import java.net.SocketException;
@@ -69,24 +69,12 @@
private boolean mRunning;
private String mDisplayName;
- public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
- final String ifname;
- final int ifindex;
- final byte[] hwaddr;
- final int mtu;
+ public ConnectivityPacketTracker(Handler h, InterfaceParams ifParams, LocalLog log) {
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
- try {
- ifname = netif.getName();
- ifindex = netif.getIndex();
- hwaddr = netif.getHardwareAddress();
- mtu = netif.getMTU();
- } catch (NullPointerException|SocketException e) {
- throw new IllegalArgumentException("bad network interface", e);
- }
-
- mTag = TAG + "." + ifname;
+ mTag = TAG + "." + ifParams.name;
mLog = log;
- mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
+ mPacketListener = new PacketListener(h, ifParams);
}
public void start(String displayName) {
@@ -102,13 +90,11 @@
}
private final class PacketListener extends PacketReader {
- private final int mIfIndex;
- private final byte mHwAddr[];
+ private final InterfaceParams mInterface;
- PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
- super(h, mtu);
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
+ PacketListener(Handler h, InterfaceParams ifParams) {
+ super(h, ifParams.defaultMtu);
+ mInterface = ifParams;
}
@Override
@@ -117,7 +103,7 @@
try {
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
- Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
+ Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index));
} catch (ErrnoException | IOException e) {
logError("Failed to create packet tracking socket: ", e);
closeFd(s);
@@ -129,7 +115,7 @@
@Override
protected void handlePacket(byte[] recvbuf, int length) {
final String summary = ConnectivityPacketSummary.summarize(
- mHwAddr, recvbuf, length);
+ mInterface.macAddr, recvbuf, length);
if (summary == null) return;
if (DBG) Log.d(mTag, summary);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index fdb366c..d3a97b3 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -35,6 +35,7 @@
import android.net.dhcp.DhcpClient;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.net.util.NetworkConstants;
@@ -63,7 +64,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
@@ -556,7 +556,7 @@
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private final InterfaceController mInterfaceCtrl;
- private NetworkInterface mNetworkInterface;
+ private InterfaceParams mInterfaceParams;
/**
* Non-final member variables accessed only from within our StateMachine.
@@ -722,7 +722,12 @@
return;
}
- getNetworkInterface();
+ mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
+ if (mInterfaceParams == null) {
+ logError("Failed to find InterfaceParams for " + mInterfaceName);
+ // TODO: call doImmediateProvisioningFailure() with an error code
+ // indicating something like "interface not ready".
+ }
mCallback.setNeighborDiscoveryOffload(true);
sendMessage(CMD_START, new ProvisioningConfiguration(req));
@@ -858,7 +863,7 @@
protected String getLogRecString(Message msg) {
final String logLine = String.format(
"%s/%d %d %d %s [%s]",
- mInterfaceName, mNetworkInterface == null ? -1 : mNetworkInterface.getIndex(),
+ mInterfaceName, (mInterfaceParams == null) ? -1 : mInterfaceParams.index,
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
@@ -889,15 +894,6 @@
mLog.log(msg);
}
- private void getNetworkInterface() {
- try {
- mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
- } catch (SocketException | NullPointerException e) {
- // TODO: throw new IllegalStateException.
- logError("Failed to get interface object: %s", e);
- }
- }
-
// This needs to be called with care to ensure that our LinkProperties
// are in sync with the actual LinkProperties of the interface. For example,
// we should only call this if we know for sure that there are no IP addresses
@@ -1218,7 +1214,7 @@
}
} else {
// Start DHCPv4.
- mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceName);
+ mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
mDhcpClient.registerForPreDhcpNotification();
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}
@@ -1245,7 +1241,7 @@
try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
- mInterfaceName,
+ mInterfaceParams,
getHandler(),
mLog,
new IpReachabilityMonitor.Callback() {
@@ -1447,7 +1443,7 @@
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
apfConfig.ethTypeBlackList =
mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
- mApfFilter = ApfFilter.maybeCreate(apfConfig, mNetworkInterface, mCallback);
+ mApfFilter = ApfFilter.maybeCreate(apfConfig, mInterfaceParams, mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1515,7 +1511,7 @@
private ConnectivityPacketTracker createPacketTracker() {
try {
return new ConnectivityPacketTracker(
- getHandler(), mNetworkInterface, mConnectivityPacketLog);
+ getHandler(), mInterfaceParams, mConnectivityPacketLog);
} catch (IllegalArgumentException e) {
return null;
}
diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java
index 6807334..fc07aa1 100644
--- a/services/net/java/android/net/ip/IpNeighborMonitor.java
+++ b/services/net/java/android/net/ip/IpNeighborMonitor.java
@@ -16,7 +16,11 @@
package android.net.ip;
-import android.net.netlink.NetlinkConstants;
+import static android.net.netlink.NetlinkConstants.hexify;
+import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
+
+import android.net.MacAddress;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.NetlinkSocket;
@@ -92,37 +96,35 @@
final int ifindex;
final InetAddress ip;
final short nudState;
- final byte[] linkLayerAddr;
+ final MacAddress macAddr;
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
- short nudState, byte[] linkLayerAddr) {
+ short nudState, MacAddress macAddr) {
this.elapsedMs = elapsedMs;
this.msgType = msgType;
this.ifindex = ifindex;
this.ip = ip;
this.nudState = nudState;
- this.linkLayerAddr = linkLayerAddr;
+ this.macAddr = macAddr;
}
boolean isConnected() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateConnected(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
}
boolean isValid() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateValid(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
}
@Override
public String toString() {
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
return j.add("@" + elapsedMs)
- .add(NetlinkConstants.stringForNlMsgType(msgType))
+ .add(stringForNlMsgType(msgType))
.add("if=" + ifindex)
.add(ip.getHostAddress())
.add(StructNdMsg.stringForNudState(nudState))
- .add("[" + NetlinkConstants.hexify(linkLayerAddr) + "]")
+ .add("[" + macAddr + "]")
.toString();
}
}
@@ -183,7 +185,7 @@
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
if (nlMsg == null || nlMsg.getHeader() == null) {
byteBuffer.position(position);
- mLog.e("unparsable netlink msg: " + NetlinkConstants.hexify(byteBuffer));
+ mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
break;
}
@@ -217,12 +219,13 @@
final int ifindex = ndMsg.ndm_ifindex;
final InetAddress destination = neighMsg.getDestination();
final short nudState =
- (msgType == NetlinkConstants.RTM_DELNEIGH)
+ (msgType == RTM_DELNEIGH)
? StructNdMsg.NUD_NONE
: ndMsg.ndm_state;
final NeighborEvent event = new NeighborEvent(
- whenMs, msgType, ifindex, destination, nudState, neighMsg.getLinkLayerAddress());
+ whenMs, msgType, ifindex, destination, nudState,
+ getMacAddress(neighMsg.getLinkLayerAddress()));
if (VDBG) {
Log.d(TAG, neighMsg.toString());
@@ -233,4 +236,16 @@
mConsumer.accept(event);
}
+
+ private static MacAddress getMacAddress(byte[] linkLayerAddress) {
+ if (linkLayerAddress != null) {
+ try {
+ return MacAddress.fromBytes(linkLayerAddress);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed to parse link-layer address: " + hexify(linkLayerAddress));
+ }
+ }
+
+ return null;
+ }
}
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index b31ffbb..7e02a28 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -26,6 +26,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
import android.net.netlink.StructNdMsg;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -46,9 +47,7 @@
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
import java.net.SocketAddress;
-import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -168,8 +167,7 @@
}
}
- private final String mInterfaceName;
- private final int mInterfaceIndex;
+ private final InterfaceParams mInterfaceParams;
private final IpNeighborMonitor mIpNeighborMonitor;
private final SharedLog mLog;
private final Callback mCallback;
@@ -182,30 +180,25 @@
private volatile long mLastProbeTimeMs;
public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback) {
- this(context, ifName, h, log, callback, null);
- }
-
- public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback,
+ Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker) {
- this(ifName, getInterfaceIndex(ifName), h, log, callback, tracker,
- Dependencies.makeDefault(context, ifName));
+ this(ifParams, h, log, callback, tracker, Dependencies.makeDefault(context, ifParams.name));
}
@VisibleForTesting
- IpReachabilityMonitor(String ifName, int ifIndex, Handler h, SharedLog log, Callback callback,
+ IpReachabilityMonitor(InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker, Dependencies dependencies) {
- mInterfaceName = ifName;
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
+
+ mInterfaceParams = ifParams;
mLog = log.forSubComponent(TAG);
mCallback = callback;
mMultinetworkPolicyTracker = tracker;
- mInterfaceIndex = ifIndex;
mDependencies = dependencies;
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
(NeighborEvent event) -> {
- if (mInterfaceIndex != event.ifindex) return;
+ if (mInterfaceParams.index != event.ifindex) return;
if (!mNeighborWatchList.containsKey(event.ip)) return;
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
@@ -241,7 +234,7 @@
private String describeWatchList(String sep) {
final StringBuilder sb = new StringBuilder();
- sb.append("iface{" + mInterfaceName + "/" + mInterfaceIndex + "}," + sep);
+ sb.append("iface{" + mInterfaceParams + "}," + sep);
sb.append("ntable=[" + sep);
String delimiter = "";
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
@@ -262,10 +255,10 @@
}
public void updateLinkProperties(LinkProperties lp) {
- if (!mInterfaceName.equals(lp.getInterfaceName())) {
+ if (!mInterfaceParams.name.equals(lp.getInterfaceName())) {
// TODO: figure out whether / how to cope with interface changes.
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
- "' does not match: " + mInterfaceName);
+ "' does not match: " + mInterfaceParams.name);
return;
}
@@ -353,10 +346,10 @@
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
}
- for (InetAddress target : ipProbeList) {
- final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceIndex, target);
+ for (InetAddress ip : ipProbeList) {
+ final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceParams.index, ip);
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
- target.getHostAddress(), rval));
+ ip.getHostAddress(), rval));
logEvent(IpReachabilityEvent.PROBE, rval);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
@@ -378,22 +371,9 @@
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
}
- private static int getInterfaceIndex(String ifname) {
- final NetworkInterface iface;
- try {
- iface = NetworkInterface.getByName(ifname);
- } catch (SocketException e) {
- throw new IllegalArgumentException("invalid interface '" + ifname + "': ", e);
- }
- if (iface == null) {
- throw new IllegalArgumentException("NetworkInterface was null for " + ifname);
- }
- return iface.getIndex();
- }
-
private void logEvent(int probeType, int errorCode) {
int eventType = probeType | (errorCode & 0xff);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
private void logNudFailed(ProvisioningChange delta) {
@@ -401,6 +381,6 @@
boolean isFromProbe = (duration < getProbeWakeLockDuration());
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
int eventType = IpReachabilityEvent.nudFailureEventType(isFromProbe, isProvisioningLost);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
}
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index cb3123c..49a1e79 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -25,6 +25,7 @@
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.TrafficStats;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructGroupReq;
@@ -96,9 +97,7 @@
(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
- private final String mIfName;
- private final int mIfIndex;
- private final byte[] mHwAddr;
+ private final InterfaceParams mInterface;
private final InetSocketAddress mAllNodes;
// This lock is to protect the RA from being updated while being
@@ -223,11 +222,9 @@
}
- public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) {
- mIfName = ifname;
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
- mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
+ public RouterAdvertisementDaemon(InterfaceParams ifParams) {
+ mInterface = ifParams;
+ mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
}
@@ -279,7 +276,7 @@
try {
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
- putSlla(ra, mHwAddr);
+ putSlla(ra, mInterface.macAddr.toByteArray());
mRaLength = ra.position();
// https://tools.ietf.org/html/rfc5175#section-4 says:
@@ -579,9 +576,9 @@
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
- Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName);
+ Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
NetworkUtils.protectFromVpn(mSocket);
- NetworkUtils.setupRaSocket(mSocket, mIfIndex);
+ NetworkUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -614,7 +611,7 @@
final InetAddress destip = dest.getAddress();
return (destip instanceof Inet6Address) &&
destip.isLinkLocalAddress() &&
- (((Inet6Address) destip).getScopeId() == mIfIndex);
+ (((Inet6Address) destip).getScopeId() == mInterface.index);
}
private void maybeSendRA(InetSocketAddress dest) {
diff --git a/services/net/java/android/net/util/ConnectivityPacketSummary.java b/services/net/java/android/net/util/ConnectivityPacketSummary.java
index dae93af..4951400 100644
--- a/services/net/java/android/net/util/ConnectivityPacketSummary.java
+++ b/services/net/java/android/net/util/ConnectivityPacketSummary.java
@@ -17,6 +17,7 @@
package android.net.util;
import android.net.dhcp.DhcpPacket;
+import android.net.MacAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -45,21 +46,20 @@
private final ByteBuffer mPacket;
private final String mSummary;
- public static String summarize(byte[] hwaddr, byte[] buffer) {
+ public static String summarize(MacAddress hwaddr, byte[] buffer) {
return summarize(hwaddr, buffer, buffer.length);
}
// Methods called herein perform some but by no means all error checking.
// They may throw runtime exceptions on malformed packets.
- public static String summarize(byte[] hwaddr, byte[] buffer, int length) {
- if ((hwaddr == null) || (hwaddr.length != ETHER_ADDR_LEN)) return null;
- if (buffer == null) return null;
+ public static String summarize(MacAddress macAddr, byte[] buffer, int length) {
+ if ((macAddr == null) || (buffer == null)) return null;
length = Math.min(length, buffer.length);
- return (new ConnectivityPacketSummary(hwaddr, buffer, length)).toString();
+ return (new ConnectivityPacketSummary(macAddr, buffer, length)).toString();
}
- private ConnectivityPacketSummary(byte[] hwaddr, byte[] buffer, int length) {
- mHwAddr = hwaddr;
+ private ConnectivityPacketSummary(MacAddress macAddr, byte[] buffer, int length) {
+ mHwAddr = macAddr.toByteArray();
mBytes = buffer;
mLength = Math.min(length, mBytes.length);
mPacket = ByteBuffer.wrap(mBytes, 0, mLength);
diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java
new file mode 100644
index 0000000..a4b2fbb
--- /dev/null
+++ b/services/net/java/android/net/util/InterfaceParams.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import static android.net.MacAddress.ALL_ZEROS_ADDRESS;
+import static android.net.util.NetworkConstants.ETHER_MTU;
+import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.net.MacAddress;
+import android.text.TextUtils;
+
+import java.net.NetworkInterface;
+import java.net.SocketException;
+
+
+/**
+ * Encapsulate the interface parameters common to IpClient/IpServer components.
+ *
+ * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
+ * and IpServer (sub)components need most or all of this information at some
+ * point during their lifecycles, so pass only this simplified object around
+ * which can be created once when IpClient/IpServer are told to start.
+ *
+ * @hide
+ */
+public class InterfaceParams {
+ public final String name;
+ public final int index;
+ public final MacAddress macAddr;
+ public final int defaultMtu;
+
+ public static InterfaceParams getByName(String name) {
+ final NetworkInterface netif = getNetworkInterfaceByName(name);
+ if (netif == null) return null;
+
+ // Not all interfaces have MAC addresses, e.g. rmnet_data0.
+ final MacAddress macAddr = getMacAddress(netif);
+
+ try {
+ return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
+ } catch (IllegalArgumentException|SocketException e) {
+ return null;
+ }
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr) {
+ this(name, index, macAddr, ETHER_MTU);
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
+ checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
+ checkArgument((index > 0), "invalid interface index");
+ this.name = name;
+ this.index = index;
+ this.macAddr = (macAddr != null) ? macAddr : ALL_ZEROS_ADDRESS;
+ this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
+ }
+
+ private static NetworkInterface getNetworkInterfaceByName(String name) {
+ try {
+ return NetworkInterface.getByName(name);
+ } catch (NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+
+ private static MacAddress getMacAddress(NetworkInterface netif) {
+ try {
+ return MacAddress.fromBytes(netif.getHardwareAddress());
+ } catch (IllegalArgumentException|NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+}
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 1ca6f26..ae311f8 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -49,7 +49,7 @@
LOCAL_JAVA_LIBRARIES := \
junit \
- platform-robolectric-3.5.1-prebuilt
+ platform-robolectric-3.6.1-prebuilt
LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib
LOCAL_MODULE := FrameworksServicesRoboTests
@@ -74,4 +74,4 @@
LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java
-include prebuilts/misc/common/robolectric/3.5.1/run_robotests.mk
+include prebuilts/misc/common/robolectric/3.6.1/run_robotests.mk
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index a473bc6..c397f23 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -57,7 +57,6 @@
final BackupManagerConstants constants =
new BackupManagerConstants(handler, context.getContentResolver());
- constants.start();
assertThat(constants.getKeyValueBackupIntervalMilliseconds())
.isEqualTo(4 * AlarmManager.INTERVAL_HOUR);
@@ -89,7 +88,6 @@
final BackupManagerConstants constants =
new BackupManagerConstants(handler, context.getContentResolver());
- constants.start();
assertThat(constants.getBackupFinishedNotificationReceivers())
.isEqualTo(new String[] {PACKAGE_NAME, ANOTHER_PACKAGE_NAME});
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java
new file mode 100644
index 0000000..f9ebd28
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -0,0 +1,341 @@
+/*
+ * 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.backup;
+
+import static com.android.server.backup.testing.TransportTestUtils.TRANSPORT_NAMES;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+import static org.testng.Assert.expectThrows;
+
+import android.app.backup.BackupManager;
+import android.app.backup.ISelectBackupTransportCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.HandlerThread;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+
+import com.android.server.backup.testing.ShadowAppBackupUtils;
+import com.android.server.backup.testing.TransportTestUtils;
+import com.android.server.backup.testing.TransportTestUtils.TransportData;
+import com.android.server.backup.transport.TransportNotRegisteredException;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderClasses;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowContextWrapper;
+import org.robolectric.shadows.ShadowLog;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSettings;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ sdk = 26,
+ shadows = {ShadowAppBackupUtils.class}
+)
+@SystemLoaderClasses({RefactoredBackupManagerService.class, TransportManager.class})
+@Presubmit
+public class BackupManagerServiceRoboTest {
+ private static final String TAG = "BMSTest";
+ private static final String TRANSPORT_NAME =
+ "com.google.android.gms/.backup.BackupTransportService";
+
+ @Mock private TransportManager mTransportManager;
+ private HandlerThread mBackupThread;
+ private ShadowLooper mShadowBackupLooper;
+ private File mBaseStateDir;
+ private File mDataDir;
+ private RefactoredBackupManagerService mBackupManagerService;
+ private ShadowContextWrapper mShadowContext;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mBackupThread = new HandlerThread("backup-test");
+ mBackupThread.setUncaughtExceptionHandler(
+ (t, e) -> ShadowLog.e(TAG, "Uncaught exception in test thread " + t.getName(), e));
+ mBackupThread.start();
+ mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
+
+ ContextWrapper context = RuntimeEnvironment.application;
+ mContext = context;
+ mShadowContext = shadowOf(context);
+
+ File cacheDir = mContext.getCacheDir();
+ mBaseStateDir = new File(cacheDir, "base_state_dir");
+ mDataDir = new File(cacheDir, "data_dir");
+
+ mBackupManagerService =
+ new RefactoredBackupManagerService(
+ mContext,
+ new Trampoline(mContext),
+ mBackupThread,
+ mBaseStateDir,
+ mDataDir,
+ mTransportManager);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mBackupThread.quit();
+ ShadowAppBackupUtils.reset();
+ }
+
+ /* Tests for destination string */
+
+ @Test
+ public void testDestinationString() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.getTransportCurrentDestinationString(eq(TRANSPORT_NAME)))
+ .thenReturn("destinationString");
+
+ String destination = mBackupManagerService.getDestinationString(TRANSPORT_NAME);
+
+ assertThat(destination).isEqualTo("destinationString");
+ }
+
+ @Test
+ public void testDestinationString_whenTransportNotRegistered() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.getTransportCurrentDestinationString(eq(TRANSPORT_NAME)))
+ .thenThrow(TransportNotRegisteredException.class);
+
+ String destination = mBackupManagerService.getDestinationString(TRANSPORT_NAME);
+
+ assertThat(destination).isNull();
+ }
+
+ @Test
+ public void testDestinationString_withoutPermission() throws Exception {
+ mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.getTransportCurrentDestinationString(eq(TRANSPORT_NAME)))
+ .thenThrow(TransportNotRegisteredException.class);
+
+ expectThrows(
+ SecurityException.class,
+ () -> mBackupManagerService.getDestinationString(TRANSPORT_NAME));
+ }
+
+ /* Tests for app eligibility */
+
+ @Test
+ public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ TransportData transport =
+ TransportTestUtils.setUpCurrentTransport(mTransportManager, TRANSPORT_NAME);
+ ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
+
+ boolean result = mBackupManagerService.isAppEligibleForBackup("app.package");
+
+ assertThat(result).isTrue();
+ verify(mTransportManager)
+ .disposeOfTransportClient(eq(transport.transportClientMock), any());
+ }
+
+ @Test
+ public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ TransportTestUtils.setUpCurrentTransport(mTransportManager, TRANSPORT_NAME);
+ ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
+
+ boolean result = mBackupManagerService.isAppEligibleForBackup("app.package");
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
+ mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+ TransportTestUtils.setUpCurrentTransport(mTransportManager, TRANSPORT_NAME);
+
+ expectThrows(
+ SecurityException.class,
+ () -> mBackupManagerService.isAppEligibleForBackup("app.package"));
+ }
+
+ @Test
+ public void testFilterAppsEligibleForBackup() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ TransportData transport =
+ TransportTestUtils.setUpCurrentTransport(mTransportManager, TRANSPORT_NAME);
+ Map<String, Boolean> packagesMap = new HashMap<>();
+ packagesMap.put("package.a", true);
+ packagesMap.put("package.b", false);
+ ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get;
+ String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]);
+
+ String[] filtered = mBackupManagerService.filterAppsEligibleForBackup(packages);
+
+ assertThat(filtered).asList().containsExactly("package.a");
+ verify(mTransportManager)
+ .disposeOfTransportClient(eq(transport.transportClientMock), any());
+ }
+
+ @Test
+ public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
+
+ String[] filtered =
+ mBackupManagerService.filterAppsEligibleForBackup(
+ new String[] {"package.a", "package.b"});
+
+ assertThat(filtered).isEmpty();
+ }
+
+ @Test
+ public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
+ mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+ TransportTestUtils.setUpCurrentTransport(mTransportManager, TRANSPORT_NAME);
+
+ expectThrows(
+ SecurityException.class,
+ () ->
+ mBackupManagerService.filterAppsEligibleForBackup(
+ new String[] {"package.a", "package.b"}));
+ }
+
+ /* Tests for select transport */
+
+ private TransportData mNewTransport;
+ private TransportData mOldTransport;
+ private ComponentName mNewTransportComponent;
+ private ISelectBackupTransportCallback mCallback;
+
+ private void setUpForSelectTransport() throws Exception {
+ List<TransportData> transports =
+ TransportTestUtils.setUpTransports(mTransportManager, TRANSPORT_NAMES);
+ mNewTransport = transports.get(0);
+ mNewTransportComponent = mNewTransport.transportClientMock.getTransportComponent();
+ mOldTransport = transports.get(1);
+ when(mTransportManager.selectTransport(eq(mNewTransport.transportName)))
+ .thenReturn(mOldTransport.transportName);
+ }
+
+ @Test
+ public void testSelectBackupTransport() throws Exception {
+ setUpForSelectTransport();
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+
+ String oldTransport =
+ mBackupManagerService.selectBackupTransport(mNewTransport.transportName);
+
+ assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
+ assertThat(oldTransport).isEqualTo(mOldTransport.transportName);
+ }
+
+ @Test
+ public void testSelectBackupTransport_withoutPermission() throws Exception {
+ setUpForSelectTransport();
+ mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+
+ expectThrows(
+ SecurityException.class,
+ () -> mBackupManagerService.selectBackupTransport(mNewTransport.transportName));
+ }
+
+ @Test
+ public void testSelectBackupTransportAsync() throws Exception {
+ setUpForSelectTransport();
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+ .thenReturn(BackupManager.SUCCESS);
+ ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+ mBackupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+ mShadowBackupLooper.runToEndOfTasks();
+ assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
+ verify(callback).onSuccess(eq(mNewTransport.transportName));
+ }
+
+ @Test
+ public void testSelectBackupTransportAsync_whenRegistrationFails() throws Exception {
+ setUpForSelectTransport();
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+ .thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
+ ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+ mBackupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+ mShadowBackupLooper.runToEndOfTasks();
+ assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName);
+ verify(callback).onFailure(anyInt());
+ }
+
+ @Test
+ public void testSelectBackupTransportAsync_whenTransportGetsUnregistered() throws Exception {
+ TransportTestUtils.setUpTransports(
+ mTransportManager, new TransportData(TRANSPORT_NAME, null, null));
+ ComponentName newTransportComponent =
+ TransportTestUtils.transportComponentName(TRANSPORT_NAME);
+ mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+ when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent)))
+ .thenReturn(BackupManager.SUCCESS);
+ ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+ mBackupManagerService.selectBackupTransportAsync(newTransportComponent, callback);
+
+ mShadowBackupLooper.runToEndOfTasks();
+ assertThat(getSettingsTransport()).isNotEqualTo(TRANSPORT_NAME);
+ verify(callback).onFailure(anyInt());
+ }
+
+ @Test
+ public void testSelectBackupTransportAsync_withoutPermission() throws Exception {
+ setUpForSelectTransport();
+ mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+ ComponentName newTransportComponent =
+ mNewTransport.transportClientMock.getTransportComponent();
+
+ expectThrows(
+ SecurityException.class,
+ () ->
+ mBackupManagerService.selectBackupTransportAsync(
+ newTransportComponent, mock(ISelectBackupTransportCallback.class)));
+ }
+
+ private String getSettingsTransport() {
+ return ShadowSettings.ShadowSecure.getString(
+ mContext.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 82830fe..acd670f 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -24,7 +24,6 @@
import static org.testng.Assert.expectThrows;
import android.annotation.Nullable;
-import android.app.backup.BackupManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -40,7 +39,6 @@
import com.android.server.backup.testing.ShadowContextImplForBackup;
import com.android.server.backup.testing.ShadowPackageManagerForBackup;
import com.android.server.backup.testing.TransportBoundListenerStub;
-import com.android.server.backup.testing.TransportReadyCallbackStub;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.testing.FrameworkRobolectricTestRunner;
@@ -87,9 +85,6 @@
private final TransportBoundListenerStub mTransportBoundListenerStub =
new TransportBoundListenerStub(true);
- private final TransportReadyCallbackStub mTransportReadyCallbackStub =
- new TransportReadyCallbackStub();
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -466,59 +461,6 @@
}
@Test
- public void ensureTransportReady_transportNotYetBound_callsListenerOnFailure()
- throws Exception {
- setUpPackageWithTransports(PACKAGE_NAME, Arrays.asList(mTransport1, mTransport2),
- ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
-
- TransportManager transportManager = new TransportManager(
- RuntimeEnvironment.application.getApplicationContext(),
- new HashSet<>(Arrays.asList(mTransport1.componentName, mTransport2.componentName)),
- mTransport1.name,
- mTransportBoundListenerStub,
- ShadowLooper.getMainLooper());
-
- transportManager.ensureTransportReady(mTransport1.componentName,
- mTransportReadyCallbackStub);
-
- assertThat(mTransportReadyCallbackStub.getSuccessCalls()).isEmpty();
- assertThat(mTransportReadyCallbackStub.getFailureCalls()).containsExactlyElementsIn(
- Collections.singleton(
- BackupManager.ERROR_TRANSPORT_UNAVAILABLE));
- }
-
- @Test
- public void ensureTransportReady_transportCannotBeBound_callsListenerOnFailure()
- throws Exception {
- TransportManager transportManager =
- createTransportManagerAndSetUpTransports(Collections.singletonList(mTransport2),
- Collections.singletonList(mTransport1), mTransport1.name);
-
- transportManager.ensureTransportReady(mTransport1.componentName,
- mTransportReadyCallbackStub);
-
- assertThat(mTransportReadyCallbackStub.getSuccessCalls()).isEmpty();
- assertThat(mTransportReadyCallbackStub.getFailureCalls()).containsExactlyElementsIn(
- Collections.singleton(
- BackupManager.ERROR_TRANSPORT_UNAVAILABLE));
- }
-
- @Test
- public void ensureTransportReady_transportsAlreadyBound_callsListenerOnSuccess()
- throws Exception {
- TransportManager transportManager =
- createTransportManagerAndSetUpTransports(Collections.singletonList(mTransport2),
- Collections.singletonList(mTransport1), mTransport1.name);
-
- transportManager.ensureTransportReady(mTransport2.componentName,
- mTransportReadyCallbackStub);
-
- assertThat(mTransportReadyCallbackStub.getSuccessCalls()).containsExactlyElementsIn(
- Collections.singleton(mTransport2.name));
- assertThat(mTransportReadyCallbackStub.getFailureCalls()).isEmpty();
- }
-
- @Test
public void getTransportClient_forRegisteredTransport_returnCorrectly() throws Exception {
TransportManager transportManager =
createTransportManagerAndSetUpTransports(
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index 73f1c2f..dfca901 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -19,6 +19,9 @@
import static android.app.backup.BackupTransport.TRANSPORT_ERROR;
import static android.app.backup.BackupTransport.TRANSPORT_OK;
+import static com.android.server.backup.testing.TransportTestUtils.TRANSPORT_NAME;
+import static com.android.server.backup.testing.TransportTestUtils.TRANSPORT_NAMES;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -30,7 +33,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
@@ -41,8 +43,9 @@
import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.TransportManager;
+import com.android.server.backup.testing.TransportTestUtils;
+import com.android.server.backup.testing.TransportTestUtils.TransportData;
import com.android.server.backup.transport.TransportClient;
-import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;
@@ -55,7 +58,6 @@
import org.robolectric.annotation.Config;
import java.io.File;
-import java.util.Arrays;
import java.util.List;
@RunWith(FrameworkRobolectricTestRunner.class)
@@ -63,14 +65,6 @@
@SystemLoaderClasses({PerformInitializeTaskTest.class, TransportManager.class})
@Presubmit
public class PerformInitializeTaskTest {
- private static final String[] TRANSPORT_NAMES = {
- "android/com.android.internal.backup.LocalTransport",
- "com.google.android.gms/.backup.migrate.service.D2dTransport",
- "com.google.android.gms/.backup.BackupTransportService"
- };
-
- private static final String TRANSPORT_NAME = TRANSPORT_NAMES[0];
-
@Mock private RefactoredBackupManagerService mBackupManagerService;
@Mock private TransportManager mTransportManager;
@Mock private OnTaskFinishedListener mListener;
@@ -113,9 +107,14 @@
performInitializeTask.run();
verify(mBackupManagerService)
- .recordInitPending(false, TRANSPORT_NAME, dirName(TRANSPORT_NAME));
+ .recordInitPending(
+ false, TRANSPORT_NAME, TransportTestUtils.transportDirName(TRANSPORT_NAME));
verify(mBackupManagerService)
- .resetBackupState(eq(new File(mBaseStateDir, dirName(TRANSPORT_NAME))));
+ .resetBackupState(
+ eq(
+ new File(
+ mBaseStateDir,
+ TransportTestUtils.transportDirName(TRANSPORT_NAME))));
}
@Test
@@ -142,7 +141,8 @@
verify(mTransport).initializeDevice();
verify(mTransport, never()).finishBackup();
verify(mBackupManagerService)
- .recordInitPending(true, TRANSPORT_NAME, dirName(TRANSPORT_NAME));
+ .recordInitPending(
+ true, TRANSPORT_NAME, TransportTestUtils.transportDirName(TRANSPORT_NAME));
}
@Test
@@ -181,7 +181,8 @@
verify(mTransport).initializeDevice();
verify(mTransport).finishBackup();
verify(mBackupManagerService)
- .recordInitPending(true, TRANSPORT_NAME, dirName(TRANSPORT_NAME));
+ .recordInitPending(
+ true, TRANSPORT_NAME, TransportTestUtils.transportDirName(TRANSPORT_NAME));
}
@Test
@@ -210,7 +211,9 @@
@Test
public void testRun_whenOnlyOneTransportFails() throws Exception {
- List<TransportData> transports = setUpTransports(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]);
+ List<TransportData> transports =
+ TransportTestUtils.setUpTransports(
+ mTransportManager, TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]);
configureTransport(transports.get(0).transportMock, TRANSPORT_ERROR, 0);
configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK);
PerformInitializeTask performInitializeTask =
@@ -226,7 +229,8 @@
@Test
public void testRun_withMultipleTransports() throws Exception {
- List<TransportData> transports = setUpTransports(TRANSPORT_NAMES);
+ List<TransportData> transports =
+ TransportTestUtils.setUpTransports(mTransportManager, TRANSPORT_NAMES);
configureTransport(transports.get(0).transportMock, TRANSPORT_OK, TRANSPORT_OK);
configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK);
configureTransport(transports.get(2).transportMock, TRANSPORT_OK, TRANSPORT_OK);
@@ -243,7 +247,9 @@
@Test
public void testRun_whenOnlyOneTransportFails_disposesAllTransports() throws Exception {
- List<TransportData> transports = setUpTransports(TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]);
+ List<TransportData> transports =
+ TransportTestUtils.setUpTransports(
+ mTransportManager, TRANSPORT_NAMES[0], TRANSPORT_NAMES[1]);
configureTransport(transports.get(0).transportMock, TRANSPORT_ERROR, 0);
configureTransport(transports.get(1).transportMock, TRANSPORT_OK, TRANSPORT_OK);
PerformInitializeTask performInitializeTask =
@@ -259,7 +265,9 @@
@Test
public void testRun_whenTransportNotRegistered() throws Exception {
- setUpTransport(new TransportData(TRANSPORT_NAME, null, null));
+ TransportTestUtils.setUpTransports(
+ mTransportManager, new TransportData(TRANSPORT_NAME, null, null));
+
PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME);
performInitializeTask.run();
@@ -272,7 +280,8 @@
@Test
public void testRun_whenOnlyOneTransportNotRegistered() throws Exception {
List<TransportData> transports =
- setUpTransports(
+ TransportTestUtils.setUpTransports(
+ mTransportManager,
new TransportData(TRANSPORT_NAMES[0], null, null),
new TransportData(TRANSPORT_NAMES[1]));
String registeredTransportName = transports.get(1).transportName;
@@ -291,7 +300,8 @@
@Test
public void testRun_whenTransportNotAvailable() throws Exception {
TransportClient transportClient = mock(TransportClient.class);
- setUpTransport(new TransportData(TRANSPORT_NAME, null, transportClient));
+ TransportTestUtils.setUpTransports(
+ mTransportManager, new TransportData(TRANSPORT_NAME, null, transportClient));
PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME);
performInitializeTask.run();
@@ -304,7 +314,8 @@
@Test
public void testRun_whenTransportThrowsDeadObjectException() throws Exception {
TransportClient transportClient = mock(TransportClient.class);
- setUpTransport(new TransportData(TRANSPORT_NAME, mTransport, transportClient));
+ TransportTestUtils.setUpTransports(
+ mTransportManager, new TransportData(TRANSPORT_NAME, mTransport, transportClient));
when(mTransport.initializeDevice()).thenThrow(DeadObjectException.class);
PerformInitializeTask performInitializeTask = createPerformInitializeTask(TRANSPORT_NAME);
@@ -332,80 +343,9 @@
when(transportMock.finishBackup()).thenReturn(finishBackupStatus);
}
- private List<TransportData> setUpTransports(String... transportNames) throws Exception {
- return setUpTransports(
- Arrays.stream(transportNames)
- .map(TransportData::new)
- .toArray(TransportData[]::new));
- }
-
- /** @see #setUpTransport(TransportData) */
- private List<TransportData> setUpTransports(TransportData... transports) throws Exception {
- for (TransportData transport : transports) {
- setUpTransport(transport);
- }
- return Arrays.asList(transports);
- }
-
private void setUpTransport(String transportName) throws Exception {
- setUpTransport(new TransportData(transportName, mTransport, mock(TransportClient.class)));
- }
-
- /**
- * Configures transport according to {@link TransportData}:
- *
- * <ul>
- * <li>{@link TransportData#transportMock} {@code null} means {@link
- * TransportClient#connectOrThrow(String)} throws {@link TransportNotAvailableException}.
- * <li>{@link TransportData#transportClientMock} {@code null} means {@link
- * TransportManager#getTransportClient(String, String)} returns {@code null}.
- * </ul>
- */
- private void setUpTransport(TransportData transport) throws Exception {
- String transportName = transport.transportName;
- String transportDirName = dirName(transportName);
- IBackupTransport transportMock = transport.transportMock;
- TransportClient transportClientMock = transport.transportClientMock;
-
- if (transportMock != null) {
- when(transportMock.name()).thenReturn(transportName);
- when(transportMock.transportDirName()).thenReturn(transportDirName);
- }
-
- if (transportClientMock != null) {
- when(transportClientMock.getTransportDirName()).thenReturn(transportDirName);
- if (transportMock != null) {
- when(transportClientMock.connectOrThrow(any())).thenReturn(transportMock);
- } else {
- when(transportClientMock.connectOrThrow(any()))
- .thenThrow(TransportNotAvailableException.class);
- }
- }
-
- when(mTransportManager.getTransportClient(eq(transportName), any()))
- .thenReturn(transportClientMock);
- }
-
- private String dirName(String transportName) {
- return transportName + "_dir_name";
- }
-
- private static class TransportData {
- private final String transportName;
- @Nullable private final IBackupTransport transportMock;
- @Nullable private final TransportClient transportClientMock;
-
- private TransportData(
- String transportName,
- @Nullable IBackupTransport transportMock,
- @Nullable TransportClient transportClientMock) {
- this.transportName = transportName;
- this.transportMock = transportMock;
- this.transportClientMock = transportClientMock;
- }
-
- private TransportData(String transportName) {
- this(transportName, mock(IBackupTransport.class), mock(TransportClient.class));
- }
+ TransportTestUtils.setUpTransport(
+ mTransportManager,
+ new TransportData(transportName, mTransport, mock(TransportClient.class)));
}
}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.java
new file mode 100644
index 0000000..73cb4c0
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/ShadowAppBackupUtils.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.backup.testing;
+
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+
+import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.utils.AppBackupUtils;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.function.Function;
+
+@Implements(AppBackupUtils.class)
+public class ShadowAppBackupUtils {
+ public static Function<String, Boolean> sAppIsRunningAndEligibleForBackupWithTransport;
+ static {
+ reset();
+ }
+
+ @Implementation
+ public static boolean appIsRunningAndEligibleForBackupWithTransport(
+ @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
+ return sAppIsRunningAndEligibleForBackupWithTransport.apply(packageName);
+ }
+
+ public static void reset() {
+ sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java b/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java
deleted file mode 100644
index bbe7eba..0000000
--- a/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.testing;
-
-import com.android.server.backup.TransportManager;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Stub implementation of TransportReadyCallback, which can tell which calls were made.
- */
-public class TransportReadyCallbackStub implements
- TransportManager.TransportReadyCallback {
- private final Set<String> mSuccessCalls = new HashSet<>();
- private final Set<Integer> mFailureCalls = new HashSet<>();
-
- @Override
- public void onSuccess(String transportName) {
- mSuccessCalls.add(transportName);
- }
-
- @Override
- public void onFailure(int reason) {
- mFailureCalls.add(reason);
- }
-
- /**
- * Returns set of transport names for which {@link #onSuccess(String)} was called.
- */
- public Set<String> getSuccessCalls() {
- return mSuccessCalls;
- }
-
- /**
- * Returns set of reasons for which {@link #onFailure(int)} } was called.
- */
- public Set<Integer> getFailureCalls() {
- return mFailureCalls;
- }
-}
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
new file mode 100644
index 0000000..9770e40
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.testing;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+
+import com.android.internal.backup.IBackupTransport;
+import com.android.server.backup.TransportManager;
+import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.transport.TransportNotAvailableException;
+import com.android.server.backup.transport.TransportNotRegisteredException;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class TransportTestUtils {
+ public static final String[] TRANSPORT_NAMES = {
+ "android/com.android.internal.backup.LocalTransport",
+ "com.google.android.gms/.backup.migrate.service.D2dTransport",
+ "com.google.android.gms/.backup.BackupTransportService"
+ };
+
+ public static final String TRANSPORT_NAME = TRANSPORT_NAMES[0];
+
+ /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
+ public static TransportData setUpCurrentTransport(
+ TransportManager transportManager, String transportName) throws Exception {
+ TransportData transport = setUpTransports(transportManager, transportName).get(0);
+ when(transportManager.getCurrentTransportClient(any()))
+ .thenReturn(transport.transportClientMock);
+ return transport;
+ }
+
+ /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
+ public static List<TransportData> setUpTransports(
+ TransportManager transportManager, String... transportNames) throws Exception {
+ return setUpTransports(
+ transportManager,
+ Arrays.stream(transportNames)
+ .map(TransportData::new)
+ .toArray(TransportData[]::new));
+ }
+
+ /** @see #setUpTransport(TransportManager, TransportData) */
+ public static List<TransportData> setUpTransports(
+ TransportManager transportManager, TransportData... transports) throws Exception {
+ for (TransportData transport : transports) {
+ setUpTransport(transportManager, transport);
+ }
+ return Arrays.asList(transports);
+ }
+
+ /**
+ * Configures transport according to {@link TransportData}:
+ *
+ * <ul>
+ * <li>{@link TransportData#transportMock} {@code null} means transport not available.
+ * <li>{@link TransportData#transportClientMock} {@code null} means transport not registered.
+ * </ul>
+ */
+ public static void setUpTransport(TransportManager transportManager, TransportData transport)
+ throws Exception {
+ String transportName = transport.transportName;
+ String transportDirName = transportDirName(transportName);
+ ComponentName transportComponent = transportComponentName(transportName);
+ IBackupTransport transportMock = transport.transportMock;
+ TransportClient transportClientMock = transport.transportClientMock;
+
+ if (transportClientMock != null) {
+ // Transport registered
+ when(transportManager.getTransportClient(eq(transportName), any()))
+ .thenReturn(transportClientMock);
+ when(transportManager.getTransportClientOrThrow(eq(transportName), any()))
+ .thenReturn(transportClientMock);
+ when(transportManager.getTransportName(transportComponent)).thenReturn(transportName);
+ when(transportManager.getTransportDirName(eq(transportName)))
+ .thenReturn(transportDirName);
+ when(transportManager.getTransportDirName(eq(transportComponent)))
+ .thenReturn(transportDirName);
+ when(transportClientMock.getTransportComponent()).thenReturn(transportComponent);
+
+ if (transportMock != null) {
+ // Transport registered and available
+ when(transportClientMock.connectOrThrow(any())).thenReturn(transportMock);
+ when(transportMock.name()).thenReturn(transportName);
+ when(transportMock.transportDirName()).thenReturn(transportDirName);
+ } else {
+ // Transport registered but unavailable
+ when(transportClientMock.connectOrThrow(any()))
+ .thenThrow(TransportNotAvailableException.class);
+ }
+ } else {
+ // Transport not registered
+ when(transportManager.getTransportClient(eq(transportName), any())).thenReturn(null);
+ when(transportManager.getTransportClientOrThrow(eq(transportName), any()))
+ .thenThrow(TransportNotRegisteredException.class);
+ when(transportManager.getTransportName(transportComponent))
+ .thenThrow(TransportNotRegisteredException.class);
+ when(transportManager.getTransportDirName(eq(transportName)))
+ .thenThrow(TransportNotRegisteredException.class);
+ when(transportManager.getTransportDirName(eq(transportComponent)))
+ .thenThrow(TransportNotRegisteredException.class);
+ }
+ }
+
+ /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
+ public static ComponentName transportComponentName(String transportName) {
+ return ComponentName.unflattenFromString(transportName);
+ }
+
+ public static String transportDirName(String transportName) {
+ return transportName + "_dir_name";
+ }
+
+ public static class TransportData {
+ public final String transportName;
+ @Nullable public final IBackupTransport transportMock;
+ @Nullable public final TransportClient transportClientMock;
+
+ public TransportData(
+ String transportName,
+ @Nullable IBackupTransport transportMock,
+ @Nullable TransportClient transportClientMock) {
+ this.transportName = transportName;
+ this.transportMock = transportMock;
+ this.transportClientMock = transportClientMock;
+ }
+
+ public TransportData(String transportName) {
+ this(transportName, mock(IBackupTransport.class), mock(TransportClient.class));
+ }
+ }
+
+ private TransportTestUtils() {}
+}
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index 4462d2a..3bc0b30 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -43,7 +43,6 @@
import com.android.server.testing.SystemLoaderClasses;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -65,7 +64,6 @@
@Mock private IBackupTransport.Stub mIBackupTransport;
private TransportClient mTransportClient;
private ComponentName mTransportComponent;
- private String mTransportDirName;
private Intent mBindIntent;
private ShadowLooper mShadowLooper;
@@ -77,14 +75,12 @@
mShadowLooper = shadowOf(mainLooper);
mTransportComponent =
new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".transport.Transport");
- mTransportDirName = mTransportComponent.toString();
mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
mTransportClient =
new TransportClient(
mContext,
mBindIntent,
mTransportComponent,
- mTransportDirName,
"1",
new Handler(mainLooper));
@@ -97,11 +93,6 @@
}
@Test
- public void testGetTransportDirName_returnsTransportDirName() {
- assertThat(mTransportClient.getTransportDirName()).isEqualTo(mTransportDirName);
- }
-
- @Test
public void testGetTransportComponent_returnsTransportComponent() {
assertThat(mTransportClient.getTransportComponent()).isEqualTo(mTransportComponent);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
similarity index 73%
rename from services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java
rename to services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
index 62fa764..f741c70 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
@@ -17,55 +17,55 @@
package com.android.server.am;
import android.app.ActivityOptions;
-import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import com.android.server.am.LaunchParamsController.LaunchParams;
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doAnswer;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_SKIP;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
/**
* Tests for exercising resizing bounds due to activity options.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.LaunchingActivityPositionerTests
+ * atest FrameworksServicesTests:ActivityLaunchParamsModifierTests
*/
@MediumTest
@Presubmit
@RunWith(AndroidJUnit4.class)
-public class LaunchingActivityPositionerTests extends ActivityTestsBase {
- private LaunchingActivityPositioner mPositioner;
+public class ActivityLaunchParamsModifierTests extends ActivityTestsBase {
+ private ActivityLaunchParamsModifier mModifier;
private ActivityManagerService mService;
private ActivityStack mStack;
private TaskRecord mTask;
private ActivityRecord mActivity;
- private Rect mCurrent;
- private Rect mResult;
+ private LaunchParams mCurrent;
+ private LaunchParams mResult;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mService = createActivityManagerService();
- mPositioner = new LaunchingActivityPositioner(mService.mStackSupervisor);
- mCurrent = new Rect();
- mResult = new Rect();
+ mModifier = new ActivityLaunchParamsModifier(mService.mStackSupervisor);
+ mCurrent = new LaunchParams();
+ mResult = new LaunchParams();
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
@@ -78,35 +78,35 @@
@Test
public void testSkippedInvocations() throws Exception {
// No specified activity should be ignored
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
null /*activity*/, null /*source*/, null /*options*/, mCurrent, mResult));
// No specified activity options should be ignored
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, null /*options*/, mCurrent, mResult));
// launch bounds specified should be ignored.
final ActivityOptions options = ActivityOptions.makeBasic();
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
// Non-resizeable records should be ignored
mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
assertFalse(mActivity.isResizeable());
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
// make record resizeable
mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
assertTrue(mActivity.isResizeable());
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
// Does not support freeform
mService.mSupportsFreeformWindowManagement = false;
assertFalse(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
mService.mSupportsFreeformWindowManagement = true;
@@ -114,15 +114,15 @@
assertTrue(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
// Invalid bounds
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
options.setLaunchBounds(new Rect(0, 0, -1, -1));
- assertEquals(RESULT_SKIP, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
// Valid bounds should cause the positioner to be applied.
options.setLaunchBounds(new Rect(0, 0, 100, 100));
- assertEquals(RESULT_DONE, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
}
@@ -136,8 +136,8 @@
final Rect proposedBounds = new Rect(20, 30, 45, 40);
options.setLaunchBounds(proposedBounds);
- assertEquals(RESULT_DONE, mPositioner.onCalculateBounds(null /*task*/, null /*layout*/,
+ assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
- assertEquals(mResult, proposedBounds);
+ assertEquals(mResult.mBounds, proposedBounds);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index ee45595..1dba39f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -21,6 +21,9 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
@@ -32,11 +35,14 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.PauseActivityItem;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
@@ -46,11 +52,13 @@
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
/**
* Tests for the {@link ActivityRecord} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
+ * atest FrameworksServicesTests:com.android.server.am.ActivityRecordTests
*/
@MediumTest
@Presubmit
@@ -101,6 +109,27 @@
}
@Test
+ public void testPausingWhenVisibleFromStopped() throws Exception {
+ mActivity.state = STOPPED;
+ mActivity.makeVisibleIfNeeded(null /* starting */);
+ assertEquals(mActivity.state, PAUSING);
+
+ final ArgumentCaptor<ClientTransaction> transaction =
+ ArgumentCaptor.forClass(ClientTransaction.class);
+ verify(mActivity.app.thread, atLeast(1)).scheduleTransaction(transaction.capture());
+
+ boolean pauseFound = false;
+
+ for (ClientTransaction targetTransaction : transaction.getAllValues()) {
+ if (targetTransaction.getLifecycleStateRequest() instanceof PauseActivityItem) {
+ pauseFound = true;
+ }
+ }
+
+ assertTrue(pauseFound);
+ }
+
+ @Test
public void testPositionLimitedAspectRatioNavBarBottom() throws Exception {
verifyPositionWithLimitedAspectRatio(NAV_BAR_BOTTOM, new Rect(0, 0, 1000, 2000), 1.5f,
new Rect(0, 0, 1000, 1500));
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 6b09363..bcbf40e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -47,7 +47,7 @@
* Tests for the {@link ActivityStack} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.ActivityStackTests
+ * atest ActivityStackTests
*/
@SmallTest
@Presubmit
@@ -104,6 +104,29 @@
}
@Test
+ public void testPrimarySplitScreenToFullscreenWhenMovedToBack() throws Exception {
+ // Create primary splitscreen stack. This will create secondary stacks and places the
+ // existing fullscreen stack on the bottom.
+ final ActivityStack primarySplitScreen = mService.mStackSupervisor.getDefaultDisplay()
+ .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+
+ // Assert windowing mode.
+ assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+ // Move primary to back.
+ primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack",
+ null /* task */);
+
+ // Assert that stack is at the bottom.
+ assertEquals(mService.mStackSupervisor.getDefaultDisplay().getIndexOf(primarySplitScreen),
+ 0);
+
+ // Ensure no longer in splitscreen.
+ assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
public void testStopActivityWhenActivityDestroyed() throws Exception {
final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index d74d994..96bf49b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -32,6 +32,7 @@
import org.mockito.invocation.InvocationOnMock;
+import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -177,6 +178,10 @@
mTaskRecord.addActivityToTop(activity);
}
+ activity.setProcess(new ProcessRecord(null, mService.mContext.getApplicationInfo(),
+ "name", 12345));
+ activity.app.thread = mock(IApplicationThread.class);
+
return activity;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
new file mode 100644
index 0000000..d9b3e1c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tests for {@link GlobalSettingsToPropertiesMapper}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class GlobalSettingsToPropertiesMapperTest {
+ private static final String[][] TEST_MAPPING = new String[][] {
+ {Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "TestProperty"}
+ };
+
+ private TestMapper mTestMapper;
+ private MockContentResolver mMockContentResolver;
+
+ @Before
+ public void setup() {
+ // Use FakeSettingsProvider to not affect global state
+ mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext());
+ mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ mTestMapper = new TestMapper(mMockContentResolver);
+ }
+
+ @Test
+ public void testUpdatePropertiesFromGlobalSettings() {
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");
+
+ mTestMapper.updatePropertiesFromGlobalSettings();
+ String propValue = mTestMapper.systemPropertiesGet("TestProperty");
+ Assert.assertEquals("testValue", propValue);
+
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
+ mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+ "TestProperty");
+ propValue = mTestMapper.systemPropertiesGet("TestProperty");
+ Assert.assertEquals("testValue2", propValue);
+
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
+ mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+ "TestProperty");
+ propValue = mTestMapper.systemPropertiesGet("TestProperty");
+ Assert.assertEquals("", propValue);
+ }
+
+ @Test
+ public void testUpdatePropertiesFromGlobalSettings_PropertyAndSettingNotPresent() {
+ // Test that empty property will not not be set if setting is not set
+ mTestMapper.updatePropertiesFromGlobalSettings();
+ String propValue = mTestMapper.systemPropertiesGet("TestProperty");
+ Assert.assertNull("Property should not be set if setting is null", propValue);
+ }
+
+ private static class TestMapper extends GlobalSettingsToPropertiesMapper {
+ private final Map<String, String> mProps = new HashMap<>();
+
+ TestMapper(ContentResolver contentResolver) {
+ super(contentResolver, TEST_MAPPING);
+ }
+
+ @Override
+ protected String systemPropertiesGet(String key) {
+ Preconditions.checkNotNull(key);
+ return mProps.get(key);
+ }
+
+ @Override
+ protected void systemPropertiesSet(String key, String value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkNotNull(key);
+ mProps.put(key, value);
+ }
+ }
+
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
new file mode 100644
index 0000000..161c287
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.am.LaunchParamsController.LaunchParams;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * Tests for exercising {@link LaunchParamsController}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:LaunchParamsControllerTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class LaunchParamsControllerTests extends ActivityTestsBase {
+ private ActivityManagerService mService;
+ private LaunchParamsController mController;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mService = createActivityManagerService();
+ mController = new LaunchParamsController(mService);
+ }
+
+ /**
+ * Makes sure positioners get values passed to controller.
+ */
+ @Test
+ public void testArgumentPropagation() {
+ final LaunchParamsModifier
+ positioner = mock(LaunchParamsModifier.class);
+ mController.registerModifier(positioner);
+
+ final ActivityRecord record = new ActivityBuilder(mService).build();
+ final ActivityRecord source = new ActivityBuilder(mService).build();
+ final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
+ final ActivityOptions options = mock(ActivityOptions.class);
+
+ mController.calculate(record.getTask(), layout, record, source, options,
+ new LaunchParams());
+ verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
+ eq(source), eq(options), any(), any());
+ }
+
+ /**
+ * Ensures positioners further down the chain are not called when RESULT_DONE is returned.
+ */
+ @Test
+ public void testEarlyExit() {
+ final LaunchParamsModifier
+ ignoredPositioner = mock(LaunchParamsModifier.class);
+ final LaunchParamsModifier earlyExitPositioner =
+ (task, layout, activity, source, options, currentParams, outParams) -> RESULT_DONE;
+
+ mController.registerModifier(ignoredPositioner);
+ mController.registerModifier(earlyExitPositioner);
+
+ mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
+ null /*source*/, null /*options*/, new LaunchParams());
+ verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(),
+ any(), any());
+ }
+
+ /**
+ * Ensures that positioners are called in the correct order.
+ */
+ @Test
+ public void testRegistration() {
+ LaunchParamsModifier earlyExitPositioner =
+ new InstrumentedPositioner(RESULT_DONE, new LaunchParams());
+
+ final LaunchParamsModifier firstPositioner = spy(earlyExitPositioner);
+
+ mController.registerModifier(firstPositioner);
+
+ mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
+ null /*source*/, null /*options*/, new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ any());
+
+ final LaunchParamsModifier secondPositioner = spy(earlyExitPositioner);
+
+ mController.registerModifier(secondPositioner);
+
+ mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
+ null /*source*/, null /*options*/, new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ any());
+ verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ any());
+ }
+
+ /**
+ * Makes sure positioners further down the registration chain are called.
+ */
+ @Test
+ public void testPassThrough() {
+ final LaunchParamsModifier
+ positioner1 = mock(LaunchParamsModifier.class);
+ final LaunchParams params = new LaunchParams();
+ params.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ params.mBounds.set(0, 0, 30, 20);
+ params.mPreferredDisplayId = 3;
+
+ final InstrumentedPositioner positioner2 = new InstrumentedPositioner(RESULT_CONTINUE,
+ params);
+
+ mController.registerModifier(positioner1);
+ mController.registerModifier(positioner2);
+
+ mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
+ null /*options*/, new LaunchParams());
+
+ verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(),
+ eq(positioner2.getLaunchParams()), any());
+ }
+
+ /**
+ * Ensures skipped results are not propagated.
+ */
+ @Test
+ public void testSkip() {
+ final LaunchParams params1 = new LaunchParams();
+ params1.mBounds.set(0, 0, 10, 10);
+ final InstrumentedPositioner positioner1 = new InstrumentedPositioner(RESULT_SKIP, params1);
+
+ final LaunchParams params2 = new LaunchParams();
+ params2.mBounds.set(0, 0, 20, 30);
+ final InstrumentedPositioner positioner2 =
+ new InstrumentedPositioner(RESULT_CONTINUE, params2);
+
+ mController.registerModifier(positioner1);
+ mController.registerModifier(positioner2);
+
+ final LaunchParams
+ result = new LaunchParams();
+
+ mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
+ null /*options*/, result);
+
+ assertEquals(result, positioner2.getLaunchParams());
+ }
+
+ /**
+ * Ensures that {@link LaunchParamsModifier} requests specifying display id during
+ * layout are honored.
+ */
+ @Test
+ public void testLayoutTaskPreferredDisplayChange() {
+ final LaunchParams params = new LaunchParams();
+ params.mPreferredDisplayId = 2;
+ final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).build();
+
+ mController.registerModifier(positioner);
+
+ doNothing().when(mService).moveStackToDisplay(anyInt(), anyInt());
+ mController.layoutTask(task, null /* windowLayout */);
+ verify(mService, times(1)).moveStackToDisplay(eq(task.getStackId()),
+ eq(params.mPreferredDisplayId));
+ }
+
+ /**
+ * Ensures that {@link LaunchParamsModifier} requests specifying windowingMode during
+ * layout are honored.
+ */
+ @Test
+ public void testLayoutTaskWindowingModeChange() {
+ final LaunchParams params = new LaunchParams();
+ final int windowingMode = WINDOWING_MODE_FREEFORM;
+ params.mWindowingMode = windowingMode;
+ final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).build();
+
+ mController.registerModifier(positioner);
+
+ final int beforeWindowMode = task.getStack().getWindowingMode();
+ assertNotEquals(beforeWindowMode, windowingMode);
+
+ mController.layoutTask(task, null /* windowLayout */);
+
+ final int afterWindowMode = task.getStack().getWindowingMode();
+ assertEquals(afterWindowMode, windowingMode);
+ }
+
+ public static class InstrumentedPositioner implements
+ LaunchParamsModifier {
+
+ final private int mReturnVal;
+ final private LaunchParams mParams;
+
+ InstrumentedPositioner(int returnVal, LaunchParams params) {
+ mReturnVal = returnVal;
+ mParams = params;
+ }
+
+ @Override
+ public int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options,
+ LaunchParams currentParams, LaunchParams outParams) {
+ outParams.set(mParams);
+ return mReturnVal;
+ }
+
+ LaunchParams getLaunchParams() {
+ return mParams;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingBoundsControllerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchingBoundsControllerTests.java
deleted file mode 100644
index 0715174..0000000
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingBoundsControllerTests.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_DONE;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_CONTINUE;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_SKIP;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests for exercising {@link LaunchingBoundsController}.
- *
- * Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.LaunchingBoundsControllerTests
- */
-@MediumTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class LaunchingBoundsControllerTests extends ActivityTestsBase {
- private LaunchingBoundsController mController;
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mController = new LaunchingBoundsController();
- }
-
- /**
- * Makes sure positioners get values passed to controller.
- */
- @Test
- public void testArgumentPropagation() {
- final ActivityManagerService service = createActivityManagerService();
- final LaunchingBoundsPositioner positioner = mock(LaunchingBoundsPositioner.class);
- mController.registerPositioner(positioner);
-
- final ActivityRecord record = new ActivityBuilder(service).build();
- final ActivityRecord source = new ActivityBuilder(service).build();
- final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
- final ActivityOptions options = mock(ActivityOptions.class);
-
- mController.calculateBounds(record.getTask(), layout, record, source, options, new Rect());
- verify(positioner, times(1)).onCalculateBounds(eq(record.getTask()), eq(layout), eq(record),
- eq(source), eq(options), any(), any());
- }
-
- /**
- * Ensures positioners further down the chain are not called when RESULT_DONE is returned.
- */
- @Test
- public void testEarlyExit() {
- final LaunchingBoundsPositioner ignoredPositioner = mock(LaunchingBoundsPositioner.class);
- final LaunchingBoundsPositioner earlyExitPositioner =
- (task, layout, activity, source, options, current, result) -> RESULT_DONE;
-
- mController.registerPositioner(ignoredPositioner);
- mController.registerPositioner(earlyExitPositioner);
-
- mController.calculateBounds(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new Rect());
- verify(ignoredPositioner, never()).onCalculateBounds(any(), any(), any(), any(), any(),
- any(), any());
- }
-
- /**
- * Ensures that positioners are called in the correct order.
- */
- @Test
- public void testRegistration() {
- LaunchingBoundsPositioner earlyExitPositioner =
- new InstrumentedPositioner(RESULT_DONE, new Rect());
-
- final LaunchingBoundsPositioner firstPositioner = spy(earlyExitPositioner);
-
- mController.registerPositioner(firstPositioner);
-
- mController.calculateBounds(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new Rect());
- verify(firstPositioner, times(1)).onCalculateBounds(any(), any(), any(), any(), any(),
- any(), any());
-
- final LaunchingBoundsPositioner secondPositioner = spy(earlyExitPositioner);
-
- mController.registerPositioner(secondPositioner);
-
- mController.calculateBounds(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new Rect());
- verify(firstPositioner, times(1)).onCalculateBounds(any(), any(), any(), any(), any(),
- any(), any());
- verify(secondPositioner, times(1)).onCalculateBounds(any(), any(), any(), any(), any(),
- any(), any());
- }
-
- /**
- * Makes sure positioners further down the registration chain are called.
- */
- @Test
- public void testPassThrough() {
- final LaunchingBoundsPositioner positioner1 = mock(LaunchingBoundsPositioner.class);
- final InstrumentedPositioner positioner2 = new InstrumentedPositioner(RESULT_CONTINUE,
- new Rect (0, 0, 30, 20));
-
- mController.registerPositioner(positioner1);
- mController.registerPositioner(positioner2);
-
- mController.calculateBounds(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new Rect());
-
- verify(positioner1, times(1)).onCalculateBounds(any(), any(), any(), any(), any(),
- eq(positioner2.getLaunchBounds()), any());
- }
-
- /**
- * Ensures skipped results are not propagated.
- */
- @Test
- public void testSkip() {
- final InstrumentedPositioner positioner1 =
- new InstrumentedPositioner(RESULT_SKIP, new Rect(0, 0, 10, 10));
-
-
- final InstrumentedPositioner positioner2 =
- new InstrumentedPositioner(RESULT_CONTINUE, new Rect(0, 0, 20, 30));
-
- mController.registerPositioner(positioner1);
- mController.registerPositioner(positioner2);
-
- final Rect resultBounds = new Rect();
-
- mController.calculateBounds(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, resultBounds);
-
- assertEquals(resultBounds, positioner2.getLaunchBounds());
- }
-
- public static class InstrumentedPositioner implements LaunchingBoundsPositioner {
- private int mReturnVal;
- private Rect mBounds;
- InstrumentedPositioner(int returnVal, Rect bounds) {
- mReturnVal = returnVal;
- mBounds = bounds;
- }
-
- @Override
- public int onCalculateBounds(TaskRecord task, ActivityInfo.WindowLayout layout,
- ActivityRecord activity, ActivityRecord source,
- ActivityOptions options, Rect current, Rect result) {
- result.set(mBounds);
- return mReturnVal;
- }
-
- Rect getLaunchBounds() {
- return mBounds;
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
similarity index 81%
rename from services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
rename to services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index 13daf3e..3d323f0 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -23,6 +23,7 @@
import android.support.test.runner.AndroidJUnit4;
import android.view.Gravity;
+
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
@@ -32,7 +33,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
@@ -42,15 +43,15 @@
/**
- * Tests for exercising resizing bounds.
+ * Tests for exercising resizing task bounds.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.LaunchingTaskPositionerTests
+ * atest FrameworksServicesTests:TaskLaunchParamsModifierTests
*/
@MediumTest
@Presubmit
@RunWith(AndroidJUnit4.class)
-public class LaunchingTaskPositionerTests extends ActivityTestsBase {
+public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
private final static int STACK_WIDTH = 100;
private final static int STACK_HEIGHT = 200;
@@ -60,10 +61,10 @@
private ActivityStack mStack;
private TaskRecord mTask;
- private LaunchingTaskPositioner mPositioner;
+ private TaskLaunchParamsModifier mPositioner;
- private Rect mCurrent;
- private Rect mResult;
+ private LaunchParamsController.LaunchParams mCurrent;
+ private LaunchParamsController.LaunchParams mResult;
@Before
@Override
@@ -79,10 +80,10 @@
// dimensions on resize.
mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
- mPositioner = new LaunchingTaskPositioner();
+ mPositioner = new TaskLaunchParamsModifier();
- mResult = new Rect();
- mCurrent = new Rect();
+ mResult = new LaunchParamsController.LaunchParams();
+ mCurrent = new LaunchParamsController.LaunchParams();
}
/**
@@ -103,9 +104,9 @@
*/
@Test
public void testLaunchNoWindowLayout() throws Exception {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculateBounds(mTask, null /*layout*/,
+ assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask, null /*layout*/,
null /*record*/, null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(getDefaultBounds(Gravity.NO_GRAVITY), mResult);
+ assertEquals(getDefaultBounds(Gravity.NO_GRAVITY), mResult.mBounds);
}
/**
@@ -115,10 +116,10 @@
*/
@Test
public void testlaunchEmptyWindowLayout() throws Exception {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculateBounds(mTask,
+ assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
new WindowLayout(0, 0, 0, 0, Gravity.NO_GRAVITY, 0, 0), null /*activity*/,
null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(mResult, getDefaultBounds(Gravity.NO_GRAVITY));
+ assertEquals(mResult.mBounds, getDefaultBounds(Gravity.NO_GRAVITY));
}
/**
@@ -148,13 +149,13 @@
private void testGravity(int gravity) {
try {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculateBounds(mTask,
+ assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
new WindowLayout(0, 0, 0, 0, gravity, 0, 0), null /*activity*/,
null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(mResult, getDefaultBounds(gravity));
+ assertEquals(mResult.mBounds, getDefaultBounds(gravity));
} finally {
- mCurrent.setEmpty();
- mResult.setEmpty();
+ mCurrent.reset();
+ mResult.reset();
}
}
@@ -178,7 +179,7 @@
final WindowLayout layout = new WindowLayout(0, 0, 0, 0, gravity, 0, 0);
// layout first task
- mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(mTask, layout);
+ mService.mStackSupervisor.getLaunchParamsController().layoutTask(mTask, layout);
// Second task will be laid out on top of the first so starting bounds is the same.
final Rect expectedBounds = new Rect(mTask.getOverrideBounds());
@@ -196,25 +197,25 @@
// layout second task
assertEquals(RESULT_CONTINUE,
- mPositioner.onCalculateBounds(secondTask, layout, null /*activity*/,
+ mPositioner.onCalculate(secondTask, layout, null /*activity*/,
null /*source*/, null /*options*/, mCurrent, mResult));
if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)
|| (gravity & (Gravity.BOTTOM | Gravity.RIGHT))
== (Gravity.BOTTOM | Gravity.RIGHT)) {
- expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep(
+ expectedBounds.offset(-TaskLaunchParamsModifier.getHorizontalStep(
mStack.getOverrideBounds()), 0);
} else if ((gravity & Gravity.TOP) == Gravity.TOP
|| (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
expectedBounds.offset(
- LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()), 0);
+ TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()), 0);
} else {
expectedBounds.offset(
- LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()),
- LaunchingTaskPositioner.getVerticalStep(mStack.getOverrideBounds()));
+ TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()),
+ TaskLaunchParamsModifier.getVerticalStep(mStack.getOverrideBounds()));
}
- assertEquals(mResult, expectedBounds);
+ assertEquals(mResult.mBounds, expectedBounds);
} finally {
// Remove task and activity to prevent influencing future tests
if (activity != null) {
@@ -232,9 +233,9 @@
bounds.set(mStack.getOverrideBounds());
final int verticalInset =
- LaunchingTaskPositioner.getFreeformStartTop(mStack.getOverrideBounds());
+ TaskLaunchParamsModifier.getFreeformStartTop(mStack.getOverrideBounds());
final int horizontalInset =
- LaunchingTaskPositioner.getFreeformStartLeft(mStack.getOverrideBounds());
+ TaskLaunchParamsModifier.getFreeformStartLeft(mStack.getOverrideBounds());
bounds.inset(horizontalInset, verticalInset);
diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
index f4c5442..766d30d 100644
--- a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -48,6 +48,7 @@
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
+// TODO: Migrate this to Robolectric and merge with BackupManagerServiceRoboTest (and remove 'Robo')
public class BackupManagerServiceTest {
private static final String TAG = "BMSTest";
private static final ComponentName TRANSPORT_COMPONENT =
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index 5105f4e..9e7ef65 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -27,6 +28,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.hardware.display.BrightnessConfiguration;
import android.os.PowerManager;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -111,12 +113,41 @@
final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
final float backlight = simple.getBrightness(lux) * PowerManager.BRIGHTNESS_ON;
assertTrue("Desired brightness should be between adjacent control points.",
- backlight > DISPLAY_LEVELS_BACKLIGHT[i-1]
+ backlight > DISPLAY_LEVELS_BACKLIGHT[i - 1]
&& backlight < DISPLAY_LEVELS_BACKLIGHT[i]);
}
}
@Test
+ public void testSimpleStrategyIgnoresNewConfiguration() {
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+
+ final int N = LUX_LEVELS.length;
+ final float[] lux = { 0f, 1f };
+ final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
+
+ BrightnessConfiguration config = new BrightnessConfiguration.Builder()
+ .setCurve(lux, nits)
+ .build();
+ strategy.setBrightnessConfiguration(config);
+ assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+ }
+
+ @Test
+ public void testSimpleStrategyIgnoresNullConfiguration() {
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+
+ strategy.setBrightnessConfiguration(null);
+ final int N = DISPLAY_LEVELS_BACKLIGHT.length;
+ final float expectedBrightness =
+ (float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON;
+ assertEquals(expectedBrightness,
+ strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01 /*tolerance*/);
+ }
+
+ @Test
public void testPhysicalStrategyMappingAtControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
@@ -142,11 +173,37 @@
final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON;
final float nits = backlightToBrightness.interpolate(backlight);
assertTrue("Desired brightness should be between adjacent control points.",
- nits > DISPLAY_LEVELS_NITS[i-1] && nits < DISPLAY_LEVELS_NITS[i]);
+ nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]);
}
}
@Test
+ public void testPhysicalStrategyUsesNewConfigurations() {
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
+ DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+
+ final float[] lux = { 0f, 1f };
+ final float[] nits = {
+ DISPLAY_RANGE_NITS[0],
+ DISPLAY_RANGE_NITS[DISPLAY_RANGE_NITS.length - 1]
+ };
+
+ BrightnessConfiguration config = new BrightnessConfiguration.Builder()
+ .setCurve(lux, nits)
+ .build();
+ strategy.setBrightnessConfiguration(config);
+ assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+
+ // Check that null returns us to the default configuration.
+ strategy.setBrightnessConfiguration(null);
+ final int N = DISPLAY_LEVELS_NITS.length;
+ final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1];
+ assertEquals(expectedBrightness,
+ strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/);
+ }
+
+ @Test
public void testDefaultStrategyIsPhysical() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT,
DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index 467b47a..14b118e 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -37,6 +37,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
@@ -50,7 +51,6 @@
import org.junit.runner.RunWith;
/**
- * TODO: Also add a test for temp power whitelist
* Tests that background restrictions on jobs work as expected.
* This test requires test-apps/JobTestApp to be installed on the device.
* To run this test from root of checkout:
@@ -144,15 +144,29 @@
awaitJobStop(DEFAULT_WAIT_TIMEOUT));
}
+ @Test
+ public void testFeatureFlag() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.FORCED_APP_STANDBY_ENABLED, 0);
+ scheduleAndAssertJobStarted();
+ setAppOpsModeAllowed(false);
+ mIActivityManager.makePackageIdle(TEST_APP_PACKAGE, UserHandle.USER_CURRENT);
+ assertFalse("Job stopped even when feature flag was disabled",
+ awaitJobStop(DEFAULT_WAIT_TIMEOUT));
+ }
+
@After
public void tearDown() throws Exception {
- Intent cancelJobsIntent = new Intent(TestJobActivity.ACTION_CANCEL_JOBS);
+ final Intent cancelJobsIntent = new Intent(TestJobActivity.ACTION_CANCEL_JOBS);
cancelJobsIntent.setComponent(new ComponentName(TEST_APP_PACKAGE, TEST_APP_ACTIVITY));
cancelJobsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(cancelJobsIntent);
mContext.unregisterReceiver(mJobStateChangeReceiver);
+ Thread.sleep(500); // To avoid race with register in the next setUp
setAppOpsModeAllowed(true);
setPowerWhiteListed(false);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.FORCED_APP_STANDBY_ENABLED, 1);
}
private void setPowerWhiteListed(boolean whitelist) throws RemoteException {
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 7cba280..ccf2aaf 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -192,11 +192,15 @@
assertTrue(FileUtils.deleteContents(storageDir));
}
+ protected void assertNotEquals(long expected, long actual) {
+ assertTrue(expected != actual);
+ }
+
protected static void assertArrayEquals(byte[] expected, byte[] actual) {
assertTrue(Arrays.equals(expected, actual));
}
- protected static void assertArrayNotSame(byte[] expected, byte[] actual) {
+ protected static void assertArrayNotEquals(byte[] expected, byte[] actual) {
assertFalse(Arrays.equals(expected, actual));
}
}
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 ff25172..2e4c74f 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -23,6 +23,7 @@
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
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.verify;
import android.app.admin.PasswordMetrics;
@@ -97,15 +98,18 @@
final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
enableSyntheticPassword();
// Performs migration
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
// SP-based verification
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
- assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ assertArrayNotEquals(primaryStorageKey,
+ mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
private void initializeCredentialUnderSP(String password, int userId) throws RemoteException {
@@ -126,8 +130,9 @@
mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD,
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
mGateKeeperService.clearSecureUserId(PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
@@ -136,11 +141,13 @@
final String BADPASSWORD = "testSyntheticPasswordVerifyCredential-badpassword";
initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
- mService.verifyCredential(BADPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
+ BADPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
}
public void testSyntheticPasswordClearCredential() throws RemoteException {
@@ -157,9 +164,10 @@
// set a new password
mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
- assertNotSame(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
@@ -176,9 +184,10 @@
// set a new password
mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
- assertNotSame(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
@@ -190,15 +199,15 @@
// Untrusted change password
mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
- assertNotSame(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertNotSame(sid ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+ assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+ assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
// Verify the password
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
}
-
public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd";
disableSyntheticPassword();
@@ -215,16 +224,20 @@
// do migration
enableSyntheticPassword();
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
// verify
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
- assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
- assertArrayNotSame(profileStorageKey, mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
+ assertArrayNotEquals(primaryStorageKey,
+ mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
+ assertArrayNotEquals(profileStorageKey,
+ mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
}
@@ -247,20 +260,26 @@
// do migration
enableSyntheticPassword();
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, MANAGED_PROFILE_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ 0, MANAGED_PROFILE_USER_ID).getResponseCode());
// verify
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, MANAGED_PROFILE_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ 0, MANAGED_PROFILE_USER_ID).getResponseCode());
assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
- assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
- assertArrayNotSame(profileStorageKey, mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
+ assertArrayNotEquals(primaryStorageKey,
+ mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
+ assertArrayNotEquals(profileStorageKey,
+ mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
}
@@ -288,9 +307,9 @@
metric.quality = PASSWORD_QUALITY_SOMETHING;
verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0,
- PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
@@ -304,7 +323,8 @@
long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ 0, PRIMARY_USER_ID).getResponseCode();
assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, handle,
@@ -312,8 +332,9 @@
mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
@@ -328,7 +349,8 @@
long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ 0, PRIMARY_USER_ID).getResponseCode();
assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.setLockCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, PASSWORD,
@@ -337,12 +359,14 @@
mService.setLockCredentialWithToken(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
handle, TOKEN.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
- public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration() throws RemoteException {
+ public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
+ throws RemoteException {
final String TOKEN = "some-high-entropy-secure-token";
enableSyntheticPassword();
long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
@@ -351,7 +375,8 @@
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
}
- public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration() throws RemoteException {
+ public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
+ throws RemoteException {
final String TOKEN = "some-high-entropy-secure-token";
initializeCredentialUnderSP(null, PRIMARY_USER_ID);
long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
@@ -360,7 +385,8 @@
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
}
- public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration() throws RemoteException {
+ public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
+ throws RemoteException {
final String TOKEN = "some-high-entropy-secure-token";
final String PASSWORD = "password";
// Set up pre-SP user password
@@ -373,9 +399,9 @@
// Token not activated immediately since user password exists
assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
// Activate token (password gets migrated to SP at the same time)
- assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
- PRIMARY_USER_ID).getResponseCode());
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
// Verify token is activated
assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
}
@@ -422,7 +448,7 @@
assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
}
- // b/34600579
+ // b/62213311
//TODO: add non-migration work profile case, and unify/un-unify transition.
//TODO: test token after user resets password
//TODO: test token based reset after unified work challenge
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 1aac8ce..f798e9c 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,6 +16,8 @@
package com.android.server.locksettings.recoverablekeystore;
+import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN;
+
import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PASSWORD;
import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PATTERN;
import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PIN;
@@ -23,11 +25,14 @@
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -70,8 +75,8 @@
private static final String WRAPPING_KEY_ALIAS = "KeySyncTaskTest/WrappingKey";
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
private static final int TEST_USER_ID = 1000;
- private static final int TEST_APP_UID = 10009;
- private static final int TEST_RECOVERY_AGENT_UID = 90873;
+ private static final int TEST_RECOVERY_AGENT_UID = 10009;
+ private static final int TEST_RECOVERY_AGENT_UID2 = 10010;
private static final long TEST_DEVICE_ID = 13295035643L;
private static final String TEST_APP_KEY_ALIAS = "rcleaver";
private static final int TEST_GENERATION_ID = 2;
@@ -101,6 +106,10 @@
mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
mKeyPair = SecureBox.genKeyPair();
+ mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
+ new int[] {TYPE_LOCKSCREEN});
+ mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
+ new int[] {TYPE_LOCKSCREEN});
mRecoverySnapshotStorage = new RecoverySnapshotStorage();
mKeySyncTask = new KeySyncTask(
@@ -110,11 +119,12 @@
TEST_USER_ID,
TEST_CREDENTIAL_TYPE,
TEST_CREDENTIAL,
+ /*credentialUpdated=*/ false,
() -> mPlatformKeyManager);
mWrappingKey = generateAndroidKeyStoreKey();
mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
- when(mPlatformKeyManager.getDecryptKey()).thenReturn(
+ when(mPlatformKeyManager.getDecryptKey(TEST_USER_ID)).thenReturn(
new PlatformDecryptionKey(TEST_GENERATION_ID, mWrappingKey));
}
@@ -198,11 +208,16 @@
@Test
public void run_doesNotSendAnythingIfNoKeysToSync() throws Exception {
- // TODO: proper test here, once we have proper implementation for checking that keys need
- // to be synced.
mKeySyncTask.run();
- assertNull(mRecoverySnapshotStorage.get(TEST_USER_ID));
+ assertNull(mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID));
+ }
+
+ @Test
+ public void run_doesNotSendAnythingIfSnapshotIsUpToDate() throws Exception {
+ mKeySyncTask.run();
+
+ assertNull(mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID));
}
@Test
@@ -211,14 +226,14 @@
mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
mRecoverableKeyStoreDb.insertKey(
TEST_USER_ID,
- TEST_APP_UID,
+ TEST_RECOVERY_AGENT_UID,
TEST_APP_KEY_ALIAS,
WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
mKeySyncTask.run();
- assertNull(mRecoverySnapshotStorage.get(TEST_USER_ID));
+ assertNull(mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID));
}
@Test
@@ -229,7 +244,7 @@
mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
mRecoverableKeyStoreDb.insertKey(
TEST_USER_ID,
- TEST_APP_UID,
+ TEST_RECOVERY_AGENT_UID,
TEST_APP_KEY_ALIAS,
WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
@@ -237,7 +252,7 @@
mKeySyncTask.run();
- assertNull(mRecoverySnapshotStorage.get(TEST_USER_ID));
+ assertNull(mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID));
}
@Test
@@ -246,7 +261,7 @@
mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
mRecoverableKeyStoreDb.insertKey(
TEST_USER_ID,
- TEST_APP_UID,
+ TEST_RECOVERY_AGENT_UID,
TEST_APP_KEY_ALIAS,
WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
@@ -255,51 +270,220 @@
mKeySyncTask.run();
- assertNull(mRecoverySnapshotStorage.get(TEST_USER_ID));
+ assertNull(mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID));
}
@Test
public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
- SecretKey applicationKey = generateKey();
- mRecoverableKeyStoreDb.setServerParameters(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_DEVICE_ID);
- mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
- mRecoverableKeyStoreDb.insertKey(
- TEST_USER_ID,
- TEST_APP_UID,
- TEST_APP_KEY_ALIAS,
- WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
+
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
-
+ SecretKey applicationKey =
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_USER_ID);
+ KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
KeyDerivationParameters keyDerivationParameters =
recoveryData.getRecoveryMetadata().get(0).getKeyDerivationParameters();
- assertEquals(KeyDerivationParameters.ALGORITHM_SHA256,
- keyDerivationParameters.getAlgorithm());
+ assertThat(keyDerivationParameters.getAlgorithm()).isEqualTo(
+ KeyDerivationParameters.ALGORITHM_SHA256);
verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
byte[] lockScreenHash = KeySyncTask.hashCredentials(
keyDerivationParameters.getSalt(),
TEST_CREDENTIAL);
- // TODO: what should counter_id be here?
+ Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
+ assertThat(counterId).isNotNull();
byte[] recoveryKey = decryptThmEncryptedKey(
lockScreenHash,
recoveryData.getEncryptedRecoveryKeyBlob(),
/*vaultParams=*/ KeySyncUtils.packVaultParams(
mKeyPair.getPublic(),
- /*counterId=*/ 1,
+ counterId,
/*maxAttempts=*/ 10,
TEST_DEVICE_ID));
List<KeyEntryRecoveryData> applicationKeys = recoveryData.getApplicationKeyBlobs();
- assertEquals(1, applicationKeys.size());
+ assertThat(applicationKeys).hasSize(1);
KeyEntryRecoveryData keyData = applicationKeys.get(0);
- assertArrayEquals(TEST_APP_KEY_ALIAS.getBytes(StandardCharsets.UTF_8), keyData.getAlias());
+ assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
+ assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
byte[] appKey = KeySyncUtils.decryptApplicationKey(
recoveryKey, keyData.getEncryptedKeyMaterial());
- assertArrayEquals(applicationKey.getEncoded(), appKey);
+ assertThat(appKey).isEqualTo(applicationKey.getEncoded());
+ }
+
+ @Test
+ public void run_setsCorrectSnapshotVersion() throws Exception {
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ SecretKey applicationKey =
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(recoveryData.getSnapshotVersion()).isEqualTo(1); // default value;
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, true);
+
+ mKeySyncTask.run();
+
+ recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(recoveryData.getSnapshotVersion()).isEqualTo(2); // Updated
+ }
+
+ @Test
+ public void run_setsCorrectTypeForPassword() throws Exception {
+ mKeySyncTask = new KeySyncTask(
+ mRecoverableKeyStoreDb,
+ mRecoverySnapshotStorage,
+ mSnapshotListenersStorage,
+ TEST_USER_ID,
+ CREDENTIAL_TYPE_PASSWORD,
+ "password",
+ /*credentialUpdated=*/ false,
+ () -> mPlatformKeyManager);
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ SecretKey applicationKey =
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
+ assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
+ isEqualTo(TYPE_PASSWORD);
+ }
+
+ @Test
+ public void run_setsCorrectTypeForPin() throws Exception {
+ mKeySyncTask = new KeySyncTask(
+ mRecoverableKeyStoreDb,
+ mRecoverySnapshotStorage,
+ mSnapshotListenersStorage,
+ TEST_USER_ID,
+ CREDENTIAL_TYPE_PASSWORD,
+ /*credential=*/ "1234",
+ /*credentialUpdated=*/ false,
+ () -> mPlatformKeyManager);
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ SecretKey applicationKey =
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
+ // Password with only digits is changed to pin.
+ assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
+ isEqualTo(TYPE_PIN);
+ }
+
+ @Test
+ public void run_setsCorrectTypeForPattern() throws Exception {
+ mKeySyncTask = new KeySyncTask(
+ mRecoverableKeyStoreDb,
+ mRecoverySnapshotStorage,
+ mSnapshotListenersStorage,
+ TEST_USER_ID,
+ CREDENTIAL_TYPE_PATTERN,
+ "12345",
+ /*credentialUpdated=*/ false,
+ () -> mPlatformKeyManager);
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ SecretKey applicationKey =
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
+ assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
+ isEqualTo(TYPE_PATTERN);
+ }
+
+ @Test
+ public void run_sendsEncryptedKeysWithTwoRegisteredAgents() throws Exception {
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_APP_KEY_ALIAS);
+ mKeySyncTask.run();
+
+ verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
+ verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID2);
+ }
+
+ @Test
+ public void run_sendsEncryptedKeysOnlyForAgentWhichActiveUserSecretType() throws Exception {
+ mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
+ new int[] {TYPE_LOCKSCREEN, 100});
+ // Snapshot will not be created during unlock event.
+ mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
+ new int[] {100});
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_APP_KEY_ALIAS);
+ mKeySyncTask.run();
+
+ verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
+ verify(mSnapshotListenersStorage, never()).
+ recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID2);
+ }
+
+ @Test
+ public void run_doesNotSendKeyToNonregisteredAgent() throws Exception {
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(false);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TEST_APP_KEY_ALIAS);
+ mKeySyncTask.run();
+
+ verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
+ verify(mSnapshotListenersStorage, never()).
+ recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID2);
+ }
+
+ private SecretKey addApplicationKey(int userId, int recoveryAgentUid, String alias)
+ throws Exception{
+ SecretKey applicationKey = generateKey();
+ mRecoverableKeyStoreDb.setServerParameters(
+ userId, recoveryAgentUid, TEST_DEVICE_ID);
+ mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, TEST_GENERATION_ID);
+
+ // Newly added key is not synced.
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, recoveryAgentUid, true);
+
+ mRecoverableKeyStoreDb.insertKey(
+ userId,
+ recoveryAgentUid,
+ alias,
+ WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
+ return applicationKey;
}
private byte[] decryptThmEncryptedKey(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index 97fbca2..b1bff70 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -78,7 +78,7 @@
mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME);
mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
mPlatformKeyManager = new PlatformKeyManager(
- USER_ID_FIXTURE, mContext, mKeyStoreProxy, mRecoverableKeyStoreDb);
+ mContext, mKeyStoreProxy, mRecoverableKeyStoreDb);
when(mContext.getSystemService(anyString())).thenReturn(mKeyguardManager);
when(mContext.getSystemServiceName(any())).thenReturn("test");
@@ -93,7 +93,7 @@
@Test
public void init_createsEncryptKeyWithCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
verify(mKeyStoreProxy).setEntry(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"),
@@ -103,14 +103,14 @@
@Test
public void init_createsEncryptKeyWithCorrectPurposes() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(KeyProperties.PURPOSE_ENCRYPT, getEncryptKeyProtection().getPurposes());
}
@Test
public void init_createsEncryptKeyWithCorrectPaddings() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertArrayEquals(
new String[] { KeyProperties.ENCRYPTION_PADDING_NONE },
@@ -119,7 +119,7 @@
@Test
public void init_createsEncryptKeyWithCorrectBlockModes() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertArrayEquals(
new String[] { KeyProperties.BLOCK_MODE_GCM },
@@ -128,14 +128,14 @@
@Test
public void init_createsEncryptKeyWithoutAuthenticationRequired() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertFalse(getEncryptKeyProtection().isUserAuthenticationRequired());
}
@Test
public void init_createsDecryptKeyWithCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
verify(mKeyStoreProxy).setEntry(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
@@ -145,14 +145,14 @@
@Test
public void init_createsDecryptKeyWithCorrectPurposes() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(KeyProperties.PURPOSE_DECRYPT, getDecryptKeyProtection().getPurposes());
}
@Test
public void init_createsDecryptKeyWithCorrectPaddings() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertArrayEquals(
new String[] { KeyProperties.ENCRYPTION_PADDING_NONE },
@@ -161,7 +161,7 @@
@Test
public void init_createsDecryptKeyWithCorrectBlockModes() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertArrayEquals(
new String[] { KeyProperties.BLOCK_MODE_GCM },
@@ -170,14 +170,14 @@
@Test
public void init_createsDecryptKeyWithAuthenticationRequired() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertTrue(getDecryptKeyProtection().isUserAuthenticationRequired());
}
@Test
public void init_createsDecryptKeyWithAuthenticationValidFor15Seconds() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(
USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS,
@@ -186,7 +186,7 @@
@Test
public void init_createsDecryptKeyBoundToTheUsersAuthentication() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(
USER_ID_FIXTURE,
@@ -195,7 +195,7 @@
@Test
public void init_createsBothKeysWithSameMaterial() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
verify(mKeyStoreProxy, times(2)).setEntry(any(), mEntryArgumentCaptor.capture(), any());
List<KeyStore.Entry> entries = mEntryArgumentCaptor.getAllValues();
@@ -206,7 +206,7 @@
@Test
public void init_savesGenerationIdToDatabase() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
assertEquals(1,
mRecoverableKeyStoreDb.getPlatformKeyGenerationId(USER_ID_FIXTURE));
@@ -214,23 +214,23 @@
@Test
public void init_setsGenerationIdTo1() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- assertEquals(1, mPlatformKeyManager.getGenerationId());
+ assertEquals(1, mPlatformKeyManager.getGenerationId(USER_ID_FIXTURE));
}
@Test
public void init_incrementsGenerationIdIfKeyIsUnavailable() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- assertEquals(2, mPlatformKeyManager.getGenerationId());
+ assertEquals(2, mPlatformKeyManager.getGenerationId(USER_ID_FIXTURE));
}
@Test
public void init_doesNotIncrementGenerationIdIfKeyAvailable() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
@@ -238,21 +238,19 @@
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- assertEquals(1, mPlatformKeyManager.getGenerationId());
+ assertEquals(1, mPlatformKeyManager.getGenerationId(USER_ID_FIXTURE));
}
@Test
public void getGenerationId_returnsMinusOneIfNotInitialized() throws Exception {
- assertEquals(-1, mPlatformKeyManager.getGenerationId());
+ assertEquals(-1, mPlatformKeyManager.getGenerationId(USER_ID_FIXTURE));
}
@Test
public void getDecryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
-
- mPlatformKeyManager.getDecryptKey();
+ mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
@@ -261,9 +259,7 @@
@Test
public void getEncryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
-
- mPlatformKeyManager.getEncryptKey();
+ mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"),
@@ -272,18 +268,18 @@
@Test
public void regenerate_incrementsTheGenerationId() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- mPlatformKeyManager.regenerate();
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
- assertEquals(2, mPlatformKeyManager.getGenerationId());
+ assertEquals(2, mPlatformKeyManager.getGenerationId(USER_ID_FIXTURE));
}
@Test
public void regenerate_generatesANewEncryptKeyWithTheCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- mPlatformKeyManager.regenerate();
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
verify(mKeyStoreProxy).setEntry(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
@@ -293,9 +289,9 @@
@Test
public void regenerate_generatesANewDecryptKeyWithTheCorrectAlias() throws Exception {
- mPlatformKeyManager.init();
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
- mPlatformKeyManager.regenerate();
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
verify(mKeyStoreProxy).setEntry(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
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 445fbde..ac2d36b 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
@@ -36,9 +36,11 @@
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
-import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
import android.security.recoverablekeystore.KeyDerivationParameters;
import android.security.recoverablekeystore.KeyEntryRecoveryData;
import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
@@ -67,9 +69,8 @@
import java.util.Map;
import java.util.Random;
-import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
-import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
@SmallTest
@@ -77,7 +78,6 @@
public class RecoverableKeyStoreManagerTest {
private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
- private static final String KEY_WRAP_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
private static final String TEST_SESSION_ID = "karlin";
private static final byte[] TEST_PUBLIC_KEY = new byte[] {
(byte) 0x30, (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a,
@@ -96,7 +96,28 @@
private static final byte[] TEST_SALT = getUtf8Bytes("salt");
private static final byte[] TEST_SECRET = getUtf8Bytes("password1234");
private static final byte[] TEST_VAULT_CHALLENGE = getUtf8Bytes("vault_challenge");
- private static final byte[] TEST_VAULT_PARAMS = getUtf8Bytes("vault_params");
+ private static final byte[] TEST_VAULT_PARAMS = new byte[] {
+ // backend_key
+ (byte) 0x04, (byte) 0xb8, (byte) 0x00, (byte) 0x11, (byte) 0x18, (byte) 0x98, (byte) 0x1d,
+ (byte) 0xf0, (byte) 0x6e, (byte) 0xb4, (byte) 0x94, (byte) 0xfe, (byte) 0x86, (byte) 0xda,
+ (byte) 0x1c, (byte) 0x07, (byte) 0x8d, (byte) 0x01, (byte) 0xb4, (byte) 0x3a, (byte) 0xf6,
+ (byte) 0x8d, (byte) 0xdc, (byte) 0x61, (byte) 0xd0, (byte) 0x46, (byte) 0x49, (byte) 0x95,
+ (byte) 0x0f, (byte) 0x10, (byte) 0x86, (byte) 0x93, (byte) 0x24, (byte) 0x66, (byte) 0xe0,
+ (byte) 0x3f, (byte) 0xd2, (byte) 0xdf, (byte) 0xf3, (byte) 0x79, (byte) 0x20, (byte) 0x1d,
+ (byte) 0x91, (byte) 0x55, (byte) 0xb0, (byte) 0xe5, (byte) 0xbd, (byte) 0x7a, (byte) 0x8b,
+ (byte) 0x32, (byte) 0x7d, (byte) 0x25, (byte) 0x53, (byte) 0xa2, (byte) 0xfc, (byte) 0xa5,
+ (byte) 0x65, (byte) 0xe1, (byte) 0xbd, (byte) 0x21, (byte) 0x44, (byte) 0x7e, (byte) 0x78,
+ (byte) 0x52, (byte) 0xfa,
+ // counter_id
+ (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00,
+ // device_parameter
+ (byte) 0x78, (byte) 0x56, (byte) 0x34, (byte) 0x12, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x0,
+ // max_attempts
+ (byte) 0x0a, (byte) 0x00, (byte) 0x00, (byte) 0x00};
+ private static final int TEST_GENERATION_ID = 2;
+ private static final int TEST_USER_ID = 10009;
private static final int KEY_CLAIMANT_LENGTH_BYTES = 16;
private static final byte[] RECOVERY_RESPONSE_HEADER =
"V1 reencrypted_recovery_key".getBytes(StandardCharsets.UTF_8);
@@ -105,20 +126,24 @@
private static final int GENERATION_ID = 1;
private static final byte[] NONCE = getUtf8Bytes("nonce");
private static final byte[] KEY_MATERIAL = getUtf8Bytes("keymaterial");
- private static final int GCM_TAG_SIZE_BITS = 128;
+ private static final String KEY_ALGORITHM = "AES";
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+ private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyStoreManagerTest/WrappingKey";
@Mock private Context mMockContext;
@Mock private RecoverySnapshotListenersStorage mMockListenersStorage;
@Mock private KeyguardManager mKeyguardManager;
+ @Mock private PlatformKeyManager mPlatformKeyManager;
private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
private File mDatabaseFile;
private RecoverableKeyStoreManager mRecoverableKeyStoreManager;
private RecoverySessionStorage mRecoverySessionStorage;
private RecoverySnapshotStorage mRecoverySnapshotStorage;
+ private PlatformEncryptionKey mPlatformEncryptionKey;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getTargetContext();
@@ -130,7 +155,11 @@
when(mMockContext.getSystemService(anyString())).thenReturn(mKeyguardManager);
when(mMockContext.getSystemServiceName(any())).thenReturn("test");
when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
- when(mKeyguardManager.isDeviceSecure(anyInt())).thenReturn(true);
+ when(mKeyguardManager.isDeviceSecure(TEST_USER_ID)).thenReturn(true);
+
+ mPlatformEncryptionKey =
+ new PlatformEncryptionKey(TEST_GENERATION_ID, generateAndroidKeyStoreKey());
+ when(mPlatformKeyManager.getEncryptKey(anyInt())).thenReturn(mPlatformEncryptionKey);
mRecoverableKeyStoreManager = new RecoverableKeyStoreManager(
mMockContext,
@@ -138,7 +167,8 @@
mRecoverySessionStorage,
Executors.newSingleThreadExecutor(),
mRecoverySnapshotStorage,
- mMockListenersStorage);
+ mMockListenersStorage,
+ mPlatformKeyManager);
}
@After
@@ -150,10 +180,13 @@
@Test
public void generateAndStoreKey_storesTheKey() throws Exception {
int uid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull();
+
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
}
@Test
@@ -163,6 +196,30 @@
}
@Test
+ public void removeKey_removesAKey() throws Exception {
+ int uid = Binder.getCallingUid();
+ mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
+
+ mRecoverableKeyStoreManager.removeKey(TEST_ALIAS);
+
+ assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNull();
+ }
+
+ @Test
+ public void removeKey_UpdatesShouldCreateSnapshot() throws Exception {
+ int uid = Binder.getCallingUid();
+ int userId = UserHandle.getCallingUserId();
+
+ mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
+ // Pretend that key was synced
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
+
+ mRecoverableKeyStoreManager.removeKey(TEST_ALIAS);
+
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
+ }
+
+ @Test
public void startRecoverySession_checksPermissionFirst() throws Exception {
mRecoverableKeyStoreManager.startRecoverySession(
TEST_SESSION_ID,
@@ -173,7 +230,7 @@
new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
verify(mMockContext, times(1))
@@ -192,7 +249,7 @@
new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
assertEquals(1, mRecoverySessionStorage.size());
@@ -212,8 +269,9 @@
TEST_VAULT_CHALLENGE,
ImmutableList.of());
fail("should have thrown");
- } catch (RemoteException e) {
- assertEquals("Only a single KeyStoreRecoveryMetadata is supported", e.getMessage());
+ } catch (ServiceSpecificException e) {
+ assertThat(e.getMessage()).startsWith(
+ "Only a single KeyStoreRecoveryMetadata is supported");
}
}
@@ -229,22 +287,44 @@
new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
fail("should have thrown");
- } catch (RemoteException e) {
+ } catch (ServiceSpecificException e) {
assertEquals("Not a valid X509 key", e.getMessage());
}
}
@Test
+ public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception {
+ byte[] vaultParams = TEST_VAULT_PARAMS.clone();
+ vaultParams[1] ^= (byte) 1; // Flip 1 bit
+ try {
+ mRecoverableKeyStoreManager.startRecoverySession(
+ TEST_SESSION_ID,
+ TEST_PUBLIC_KEY,
+ vaultParams,
+ TEST_VAULT_CHALLENGE,
+ ImmutableList.of(
+ new KeyStoreRecoveryMetadata(
+ TYPE_LOCKSCREEN,
+ TYPE_PASSWORD,
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
+ TEST_SECRET)));
+ fail("should have thrown");
+ } catch (ServiceSpecificException e) {
+ assertThat(e.getMessage()).contains("do not match");
+ }
+ }
+
+ @Test
public void recoverKeys_throwsIfNoSessionIsPresent() throws Exception {
try {
mRecoverableKeyStoreManager.recoverKeys(
TEST_SESSION_ID,
/*recoveryKeyBlob=*/ randomBytes(32),
/*applicationKeys=*/ ImmutableList.of(
- new KeyEntryRecoveryData(getUtf8Bytes("alias"), randomBytes(32))
+ new KeyEntryRecoveryData("alias", randomBytes(32))
));
fail("should have thrown");
} catch (ServiceSpecificException e) {
@@ -262,7 +342,7 @@
ImmutableList.of(new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
try {
@@ -273,7 +353,6 @@
fail("should have thrown");
} catch (ServiceSpecificException e) {
assertThat(e.getMessage()).startsWith("Failed to decrypt recovery key");
- //assertEquals("Failed to decrypt recovery key", e.getMessage());
}
}
@@ -287,7 +366,7 @@
ImmutableList.of(new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID)
.getKeyClaimant();
@@ -295,7 +374,7 @@
byte[] encryptedClaimResponse = encryptClaimResponse(
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
KeyEntryRecoveryData badApplicationKey = new KeyEntryRecoveryData(
- TEST_ALIAS.getBytes(StandardCharsets.UTF_8),
+ TEST_ALIAS,
randomBytes(32));
try {
@@ -304,8 +383,8 @@
/*encryptedRecoveryKey=*/ encryptedClaimResponse,
/*applicationKeys=*/ ImmutableList.of(badApplicationKey));
fail("should have thrown");
- } catch (RemoteException e) {
- assertEquals("Failed to recover key with alias 'nick'", e.getMessage());
+ } catch (ServiceSpecificException e) {
+ assertThat(e.getMessage()).startsWith("Failed to recover key with alias 'nick'");
}
}
@@ -319,7 +398,7 @@
ImmutableList.of(new KeyStoreRecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
- KeyDerivationParameters.createSHA256Parameters(TEST_SALT),
+ KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SECRET)));
byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID)
.getKeyClaimant();
@@ -328,7 +407,7 @@
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
byte[] applicationKeyBytes = randomBytes(32);
KeyEntryRecoveryData applicationKey = new KeyEntryRecoveryData(
- TEST_ALIAS.getBytes(StandardCharsets.UTF_8),
+ TEST_ALIAS,
encryptedApplicationKey(recoveryKey, applicationKeyBytes));
Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys(
@@ -466,4 +545,16 @@
new Random().nextBytes(bytes);
return bytes;
}
+
+ private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KEY_ALGORITHM,
+ ANDROID_KEY_STORE_PROVIDER);
+ keyGenerator.init(new KeyGenParameterSpec.Builder(
+ WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index a8c7d5e..b8080ab 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -40,6 +40,7 @@
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.ECGenParameterSpec;
+import java.util.List;
import java.util.Map;
@SmallTest
@@ -113,6 +114,22 @@
}
@Test
+ public void removeKey_removesAKey() {
+ int userId = 6;
+ int uid = 60001;
+ String alias = "rupertbates";
+ WrappedKey key = new WrappedKey(
+ getUtf8Bytes("nonce1"),
+ getUtf8Bytes("key1"),
+ /*platformKeyGenerationId=*/ 1);
+ mRecoverableKeyStoreDb.insertKey(userId, uid, alias, key);
+
+ assertTrue(mRecoverableKeyStoreDb.removeKey(uid, alias));
+
+ assertNull(mRecoverableKeyStoreDb.getKey(uid, alias));
+ }
+
+ @Test
public void getKey_returnsNullIfNoKey() {
WrappedKey key = mRecoverableKeyStoreDb.getKey(
/*userId=*/ 1, /*alias=*/ "hello");
@@ -151,7 +168,7 @@
WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId);
mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey);
- Map<String, WrappedKey> keys = mRecoverableKeyStoreDb.getAllKeys(userId, generationId);
+ Map<String, WrappedKey> keys = mRecoverableKeyStoreDb.getAllKeys(userId, uid, generationId);
assertEquals(1, keys.size());
assertTrue(keys.containsKey(alias));
@@ -173,7 +190,7 @@
userId, uid, /*alias=*/ "test", wrappedKey);
Map<String, WrappedKey> keys = mRecoverableKeyStoreDb.getAllKeys(
- userId, /*generationId=*/ 7);
+ userId, uid, /*generationId=*/ 7);
assertTrue(keys.isEmpty());
}
@@ -188,7 +205,7 @@
/*userId=*/ 1, uid, /*alias=*/ "test", wrappedKey);
Map<String, WrappedKey> keys = mRecoverableKeyStoreDb.getAllKeys(
- /*userId=*/ 2, generationId);
+ /*userId=*/ 2, uid, generationId);
assertTrue(keys.isEmpty());
}
@@ -328,17 +345,33 @@
}
@Test
- public void getRecoveryAgentUid_returnsUidIfSet() throws Exception {
+ public void getRecoveryAgents_returnsUidIfSet() throws Exception {
int userId = 12;
int uid = 190992;
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid, genRandomPublicKey());
- assertThat(mRecoverableKeyStoreDb.getRecoveryAgentUid(userId)).isEqualTo(uid);
+ assertThat(mRecoverableKeyStoreDb.getRecoveryAgents(userId)).contains(uid);
}
@Test
- public void getRecoveryAgentUid_returnsMinusOneForNonexistentAgent() throws Exception {
- assertThat(mRecoverableKeyStoreDb.getRecoveryAgentUid(12)).isEqualTo(-1);
+ public void getRecoveryAgents_returnsEmptyListIfThereAreNoAgents() throws Exception {
+ int userId = 12;
+ assertThat(mRecoverableKeyStoreDb.getRecoveryAgents(userId)).isEmpty();
+ assertThat(mRecoverableKeyStoreDb.getRecoveryAgents(userId)).isNotNull();
+ }
+
+ @Test
+ public void getRecoveryAgents_withTwoAgents() throws Exception {
+ int userId = 12;
+ int uid1 = 190992;
+ int uid2 = 190993;
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid1, genRandomPublicKey());
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid2, genRandomPublicKey());
+ List<Integer> agents = mRecoverableKeyStoreDb.getRecoveryAgents(userId);
+
+ assertThat(agents).hasSize(2);
+ assertThat(agents).contains(uid1);
+ assertThat(agents).contains(uid2);
}
public void setRecoverySecretTypes_emptyDefaultValue() throws Exception {
@@ -479,6 +512,52 @@
}
@Test
+ public void setCounterId_defaultValueAndTwoUpdates() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ long value1 = 111L;
+ long value2 = 222L;
+ assertThat(mRecoverableKeyStoreDb.getCounterId(userId, uid)).isNull();
+
+ mRecoverableKeyStoreDb.setCounterId(userId, uid, value1);
+ assertThat(mRecoverableKeyStoreDb.getCounterId(userId, uid)).isEqualTo(
+ value1);
+
+ mRecoverableKeyStoreDb.setCounterId(userId, uid, value2);
+ assertThat(mRecoverableKeyStoreDb.getCounterId(userId, uid)).isEqualTo(
+ value2);
+ }
+
+ @Test
+ public void setSnapshotVersion_defaultValueAndTwoUpdates() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ long value1 = 111L;
+ long value2 = 222L;
+ assertThat(mRecoverableKeyStoreDb.getSnapshotVersion(userId, uid)).isNull();
+ mRecoverableKeyStoreDb.setSnapshotVersion(userId, uid, value1);
+ assertThat(mRecoverableKeyStoreDb.getSnapshotVersion(userId, uid)).isEqualTo(
+ value1);
+ mRecoverableKeyStoreDb.setSnapshotVersion(userId, uid, value2);
+ assertThat(mRecoverableKeyStoreDb.getSnapshotVersion(userId, uid)).isEqualTo(
+ value2);
+ }
+
+ @Test
+ public void setShouldCreateSnapshot_defaultValueAndTwoUpdates() throws Exception {
+ int userId = 12;
+ int uid = 10009;
+ boolean value1 = true;
+ boolean value2 = false;
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isEqualTo(false);
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, value1);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isEqualTo(value1);
+ mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, value2);
+ assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isEqualTo(
+ value2);
+ }
+
+ @Test
public void setRecoveryServiceMetadataEntry_allowsAUserToHaveTwoUids() throws Exception {
int userId = 12;
int uid1 = 10009;
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index d1e0132..62f7cd0 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -43,6 +43,7 @@
public boolean inMultiWindowMode;
public boolean visible = true;
public int surfaceLayer = 1;
+ public boolean isDimming = false;
public boolean policyVisible = true;
@@ -221,7 +222,7 @@
@Override
public boolean isDimming() {
- throw new UnsupportedOperationException("not implemented");
+ return isDimming;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
new file mode 100644
index 0000000..64637f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+
+import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
+import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.graphics.PixelFormat;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class PhoneWindowManagerTest {
+
+ private static FakeWindowState createOpaqueFullscreen(boolean hasLightNavBar) {
+ final FakeWindowState state = new FakeWindowState();
+ state.attrs = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT,
+ TYPE_BASE_APPLICATION,
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ PixelFormat.OPAQUE);
+ state.attrs.subtreeSystemUiVisibility =
+ hasLightNavBar ? SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0;
+ return state;
+ }
+
+ private static FakeWindowState createDimmingDialogWindow(boolean canBeImTarget) {
+ final FakeWindowState state = new FakeWindowState();
+ state.attrs = new WindowManager.LayoutParams(WRAP_CONTENT, WRAP_CONTENT,
+ TYPE_APPLICATION,
+ FLAG_DIM_BEHIND | (canBeImTarget ? 0 : FLAG_ALT_FOCUSABLE_IM),
+ PixelFormat.TRANSLUCENT);
+ state.isDimming = true;
+ return state;
+ }
+
+ private static FakeWindowState createInputMethodWindow(boolean visible, boolean drawNavBar,
+ boolean hasLightNavBar) {
+ final FakeWindowState state = new FakeWindowState();
+ state.attrs = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT,
+ TYPE_INPUT_METHOD,
+ FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN
+ | (drawNavBar ? FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS : 0),
+ PixelFormat.TRANSPARENT);
+ state.attrs.subtreeSystemUiVisibility =
+ hasLightNavBar ? SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0;
+ state.visible = visible;
+ state.policyVisible = visible;
+ return state;
+ }
+
+
+ @Test
+ public void testChooseNavigationColorWindowLw() throws Exception {
+ final FakeWindowState opaque = createOpaqueFullscreen(false);
+
+ final FakeWindowState dimmingImTarget = createDimmingDialogWindow(true);
+ final FakeWindowState dimmingNonImTarget = createDimmingDialogWindow(false);
+
+ final FakeWindowState visibleIme = createInputMethodWindow(true, true, false);
+ final FakeWindowState invisibleIme = createInputMethodWindow(false, true, false);
+ final FakeWindowState imeNonDrawNavBar = createInputMethodWindow(true, false, false);
+
+ // If everything is null, return null
+ assertNull(null, PhoneWindowManager.chooseNavigationColorWindowLw(
+ null, null, null, NAV_BAR_BOTTOM));
+
+ assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, null, NAV_BAR_BOTTOM));
+ assertEquals(dimmingImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingImTarget, null, NAV_BAR_BOTTOM));
+ assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingNonImTarget, null, NAV_BAR_BOTTOM));
+
+ assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
+ null, null, visibleIme, NAV_BAR_BOTTOM));
+ assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
+ null, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM));
+ assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ null, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM));
+ assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, visibleIme, NAV_BAR_BOTTOM));
+ assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM));
+ assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM));
+
+ assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, invisibleIme, NAV_BAR_BOTTOM));
+ assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, invisibleIme, NAV_BAR_BOTTOM));
+ assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, visibleIme, NAV_BAR_RIGHT));
+
+ // Only IME windows that have FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS should be navigation color
+ // window.
+ assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, opaque, imeNonDrawNavBar, NAV_BAR_BOTTOM));
+ assertEquals(dimmingImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
+ assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
+ opaque, dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
+ }
+
+ @Test
+ public void testUpdateLightNavigationBarLw() throws Exception {
+ final FakeWindowState opaqueDarkNavBar = createOpaqueFullscreen(false);
+ final FakeWindowState opaqueLightNavBar = createOpaqueFullscreen(true);
+
+ final FakeWindowState dimming = createDimmingDialogWindow(false);
+
+ final FakeWindowState imeDrawDarkNavBar = createInputMethodWindow(true,true, false);
+ final FakeWindowState imeDrawLightNavBar = createInputMethodWindow(true,true, true);
+
+ assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, null, null,
+ null, null));
+
+ // Opaque top fullscreen window overrides SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR flag.
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ 0, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar));
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueDarkNavBar, opaqueDarkNavBar, null,
+ opaqueDarkNavBar));
+ assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ PhoneWindowManager.updateLightNavigationBarLw(0, opaqueLightNavBar,
+ opaqueLightNavBar, null, opaqueLightNavBar));
+ assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ PhoneWindowManager.updateLightNavigationBarLw(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar));
+
+ // Dimming window clears SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ 0, opaqueDarkNavBar, dimming, null, dimming));
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ 0, opaqueLightNavBar, dimming, null, dimming));
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueDarkNavBar, dimming, null, dimming));
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, dimming, null, dimming));
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, dimming, imeDrawLightNavBar,
+ dimming));
+
+ // IME window clears SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, null, null, imeDrawDarkNavBar,
+ imeDrawDarkNavBar));
+
+ // Even if the top fullscreen has SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, IME window wins.
+ assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, opaqueLightNavBar,
+ imeDrawDarkNavBar, imeDrawDarkNavBar));
+
+ // IME window should be able to use SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.
+ assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ PhoneWindowManager.updateLightNavigationBarLw(0, opaqueDarkNavBar,
+ opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index b62d724..7b06648 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -21,6 +21,10 @@
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.app.usage.UsageStatsManager;
import android.os.FileUtils;
import android.test.AndroidTestCase;
@@ -117,4 +121,16 @@
assertFalse(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_FREQUENT));
}
+
+ public void testJobRunTime() throws Exception {
+ AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
+
+ aih.setLastJobRunTime(PACKAGE_1, USER_ID, 2000);
+ assertEquals(Long.MAX_VALUE, aih.getTimeSinceLastJobRun(PACKAGE_2, USER_ID, 0));
+ assertEquals(4000, aih.getTimeSinceLastJobRun(PACKAGE_1, USER_ID, 6000));
+
+ aih.setLastJobRunTime(PACKAGE_2, USER_ID, 6000);
+ assertEquals(1000, aih.getTimeSinceLastJobRun(PACKAGE_2, USER_ID, 7000));
+ assertEquals(5000, aih.getTimeSinceLastJobRun(PACKAGE_1, USER_ID, 7000));
+ }
}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index b792d82..725fb21 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -51,6 +51,8 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
@@ -69,6 +71,8 @@
* Unit test for AppStandbyController.
*/
@RunWith(AndroidJUnit4.class)
+@Presubmit
+@SmallTest
public class AppStandbyControllerTests {
private static final String PACKAGE_1 = "com.example.foo";
@@ -285,6 +289,10 @@
true);
}
+ private void assertBucket(int bucket) {
+ assertEquals(bucket, getStandbyBucket(mController));
+ }
+
@Test
public void testBuckets() throws Exception {
assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
@@ -425,4 +433,27 @@
REASON_PREDICTED, 2 * HOUR_MS);
assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
}
+
+ @Test
+ public void testTimeout() throws Exception {
+ setChargingState(mController, false);
+
+ reportEvent(mController, USER_INTERACTION, 0);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ mInjector.mElapsedRealtime = 2000;
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_ACTIVE);
+
+ // bucketing works after timeout
+ mInjector.mElapsedRealtime = FREQUENT_THRESHOLD - 100;
+ mController.checkIdleStates(USER_ID);
+ assertBucket(STANDBY_BUCKET_WORKING_SET);
+
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
+ REASON_PREDICTED, mInjector.mElapsedRealtime);
+ assertBucket(STANDBY_BUCKET_FREQUENT);
+
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 693264c..2284bbb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -37,13 +37,18 @@
import android.annotation.SuppressLint;
import android.content.res.Configuration;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.DisplayMetrics;
import android.util.SparseIntArray;
+import android.view.DisplayCutout;
import android.view.MotionEvent;
+import android.view.Surface;
import java.util.Arrays;
import java.util.LinkedList;
@@ -53,7 +58,7 @@
* Tests for the {@link DisplayContent} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
+ * atest com.android.server.wm.DisplayContentTests
*/
@SmallTest
@Presubmit
@@ -385,6 +390,38 @@
}
@Test
+ public void testDisplayCutout_rot0() throws Exception {
+ synchronized (sWm.getWindowManagerLock()) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInitialDisplayWidth = 200;
+ dc.mInitialDisplayHeight = 400;
+ final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
+
+ dc.mInitialDisplayCutout = cutout;
+ dc.setRotation(Surface.ROTATION_0);
+ dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
+
+ assertEquals(cutout, dc.getDisplayInfo().displayCutout);
+ }
+ }
+
+ @Test
+ public void testDisplayCutout_rot90() throws Exception {
+ synchronized (sWm.getWindowManagerLock()) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInitialDisplayWidth = 200;
+ dc.mInitialDisplayHeight = 400;
+ final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
+
+ dc.mInitialDisplayCutout = cutout;
+ dc.setRotation(Surface.ROTATION_90);
+ dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
+
+ assertEquals(createCutout(new Rect(0, 80, 10, 120)), dc.getDisplayInfo().displayCutout);
+ }
+ }
+
+ @Test
@SuppressLint("InlinedApi")
public void testOrientationDefinedByKeyguard() {
final DisplayContent dc = createNewDisplay();
@@ -449,4 +486,10 @@
y,
metaState);
}
+
+ private DisplayCutout createCutout(Rect r) {
+ Path p = new Path();
+ p.addRect(r.left, r.top, r.right, r.bottom, Path.Direction.CCW);
+ return DisplayCutout.fromBounds(p);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 17fe642..b36c7d9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -34,8 +34,10 @@
import android.graphics.Matrix;
import android.graphics.Point;
import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
import android.view.SurfaceControl;
@@ -135,6 +137,7 @@
assertFinishCallbackNotCalled();
}
+ @FlakyTest(bugId = 71719744)
@Test
public void testCancel_sneakyCancelBeforeUpdate() throws Exception {
mSurfaceAnimationRunner = new SurfaceAnimationRunner(null, () -> new ValueAnimator() {
@@ -157,9 +160,27 @@
when(mMockAnimationSpec.getDuration()).thenReturn(200L);
mSurfaceAnimationRunner.startAnimation(mMockAnimationSpec, mMockSurface, mMockTransaction,
this::finishedCallback);
+
+ // We need to wait for two frames: The first frame starts the animation, the second frame
+ // actually cancels the animation.
+ waitUntilNextFrame();
+ waitUntilNextFrame();
+ assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+ verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L));
+ }
+
+ @Test
+ public void testDeferStartingAnimations() throws Exception {
+ mSurfaceAnimationRunner.deferStartingAnimations();
+ mSurfaceAnimationRunner.startAnimation(createTranslateAnimation(), mMockSurface,
+ mMockTransaction, this::finishedCallback);
+ waitUntilNextFrame();
+ assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+ mSurfaceAnimationRunner.continueStartingAnimations();
waitUntilNextFrame();
assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
- verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L));
+ mFinishCallbackLatch.await(1, SECONDS);
+ assertFinishCallbackCalled();
}
private void waitUntilNextFrame() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 463ceeb..64c3037 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -75,10 +75,7 @@
mAnimatable2 = new MyAnimatable();
}
- // TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
- // mark them as ignore.
@Test
- @Ignore
public void testRunAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
@@ -88,17 +85,13 @@
verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
callbackCaptor.getValue().onAnimationFinished(mSpec);
- waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
// TODO: Verify reparenting once we use mPendingTransaction to reparent it back
}
- // TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
- // mark them as ignore.
@Test
- @Ignore
public void testOverrideAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
final SurfaceControl firstLeash = mAnimatable.mLeash;
@@ -114,13 +107,11 @@
// First animation was finished, but this shouldn't cancel the second animation
callbackCaptor.getValue().onAnimationFinished(mSpec);
- waitUntilPrepareSurfaces();
assertTrue(mAnimatable.mSurfaceAnimator.isAnimating());
// Second animation was finished
verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture());
callbackCaptor.getValue().onAnimationFinished(mSpec2);
- waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
}
@@ -157,10 +148,7 @@
assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
}
- // TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
- // mark them as ignore.
@Test
- @Ignore
public void testTransferAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
@@ -175,7 +163,6 @@
assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash);
assertFalse(mAnimatable.mPendingDestroySurfaces.contains(leash));
callbackCaptor.getValue().onAnimationFinished(mSpec);
- waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable2);
assertTrue(mAnimatable2.mFinishedCallbackCalled);
assertTrue(mAnimatable2.mPendingDestroySurfaces.contains(leash));
@@ -191,14 +178,6 @@
assertNull(animatable.mSurfaceAnimator.getAnimation());
}
- private void waitUntilPrepareSurfaces() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- synchronized (sWm.mWindowMap) {
- sWm.mAnimator.addAfterPrepareSurfacesRunnable(latch::countDown);
- }
- latch.await();
- }
-
private class MyAnimatable implements Animatable {
final SurfaceControl mParent;
@@ -219,7 +198,7 @@
.build();
mFinishedCallbackCalled = false;
mLeash = null;
- mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm);
+ mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, Runnable::run, sWm);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index c735341..a317706 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -588,6 +588,7 @@
return false;
}
+ @NavigationBarPosition
@Override
public int getNavBarPosition() {
return NAV_BAR_BOTTOM;
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 9cdef16..f8db4fa 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -72,6 +73,19 @@
}
@Test
+ public void testApply_clipAfterOffsetPosition() {
+ // Stack bounds is (0, 0, 10, 10) position is (20, 40)
+ WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation,
+ new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */,
+ STACK_CLIP_AFTER_ANIM);
+ windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
+ verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
+ verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
+ argThat(rect -> rect.left == 20 && rect.top == 40 && rect.right == 30
+ && rect.bottom == 50));
+ }
+
+ @Test
public void testApply_clipBeforeNoAnimationBounds() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 67db5f4..7be203a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import android.util.MergedConfiguration;
import android.view.WindowManager;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,8 +44,7 @@
/**
* Tests for the {@link WindowState} class.
*
- * Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
+ * atest FrameworksServicesTests:com.android.server.wm.WindowStateTests
*/
@SmallTest
@Presubmit
@@ -213,6 +211,18 @@
testPrepareWindowToDisplayDuringRelayout(true /*wasVisible*/);
}
+ @Test
+ public void testCanAffectSystemUiFlags() throws Exception {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ app.mToken.setHidden(false);
+ assertTrue(app.canAffectSystemUiFlags());
+ app.mToken.setHidden(true);
+ assertFalse(app.canAffectSystemUiFlags());
+ app.mToken.setHidden(false);
+ app.mAttrs.alpha = 0.0f;
+ assertFalse(app.canAffectSystemUiFlags());
+ }
+
private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index ff840f3..c699a94 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -103,7 +103,6 @@
context.getDisplay().getDisplayInfo(mDisplayInfo);
mDisplayContent = createNewDisplay();
- sWm.mAnimator.mInitialized = true;
sWm.mDisplayEnabled = true;
sWm.mDisplayReady = true;
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
new file mode 100644
index 0000000..40a10e0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.wm.utils;
+
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.*;
+
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.PointF;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+
+public class CoordinateTransformsTest {
+
+ private static final int W = 200;
+ private static final int H = 400;
+
+ private final Matrix mMatrix = new Matrix();
+
+ @Rule
+ public final ErrorCollector mErrorCollector = new ErrorCollector();
+
+ @Before
+ public void setUp() throws Exception {
+ mMatrix.setTranslate(0xdeadbeef, 0xdeadbeef);
+ }
+
+ @Test
+ public void transformPhysicalToLogicalCoordinates_rot0() throws Exception {
+ transformPhysicalToLogicalCoordinates(ROTATION_0, W, H, mMatrix);
+ assertThat(mMatrix, is(Matrix.IDENTITY_MATRIX));
+ }
+
+ @Test
+ public void transformPhysicalToLogicalCoordinates_rot90() throws Exception {
+ transformPhysicalToLogicalCoordinates(ROTATION_90, W, H, mMatrix);
+
+ checkDevicePoint(0, 0).mapsToLogicalPoint(0, W);
+ checkDevicePoint(W, H).mapsToLogicalPoint(H, 0);
+ }
+
+ @Test
+ public void transformPhysicalToLogicalCoordinates_rot180() throws Exception {
+ transformPhysicalToLogicalCoordinates(ROTATION_180, W, H, mMatrix);
+
+ checkDevicePoint(0, 0).mapsToLogicalPoint(W, H);
+ checkDevicePoint(W, H).mapsToLogicalPoint(0, 0);
+ }
+
+ @Test
+ public void transformPhysicalToLogicalCoordinates_rot270() throws Exception {
+ transformPhysicalToLogicalCoordinates(ROTATION_270, W, H, mMatrix);
+
+ checkDevicePoint(0, 0).mapsToLogicalPoint(H, 0);
+ checkDevicePoint(W, H).mapsToLogicalPoint(0, W);
+ }
+
+ private DevicePointAssertable checkDevicePoint(int x, int y) {
+ final Point devicePoint = new Point(x, y);
+ final float[] fs = new float[] {x, y};
+ mMatrix.mapPoints(fs);
+ final PointF transformedPoint = new PointF(fs[0], fs[1]);
+
+ return (expectedX, expectedY) -> {
+ mErrorCollector.checkThat("t(" + devicePoint + ")",
+ transformedPoint, is(new PointF(expectedX, expectedY)));
+ };
+ }
+
+ public interface DevicePointAssertable {
+ void mapsToLogicalPoint(int x, int y);
+ }
+}
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
index 58f0ded..a60d715 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
@@ -47,7 +47,7 @@
public void testSingleString() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putString(Notification.EXTRA_PEOPLE, expected[0]);
+ bundle.putString(Notification.EXTRA_PEOPLE_LIST, expected[0]);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("string should be in result[0]", expected, result);
}
@@ -56,7 +56,7 @@
public void testSingleCharArray() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putCharArray(Notification.EXTRA_PEOPLE, expected[0].toCharArray());
+ bundle.putCharArray(Notification.EXTRA_PEOPLE_LIST, expected[0].toCharArray());
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("char[] should be in result[0]", expected, result);
}
@@ -65,7 +65,7 @@
public void testSingleCharSequence() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putCharSequence(Notification.EXTRA_PEOPLE, new SpannableString(expected[0]));
+ bundle.putCharSequence(Notification.EXTRA_PEOPLE_LIST, new SpannableString(expected[0]));
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("charSequence should be in result[0]", expected, result);
}
@@ -74,7 +74,7 @@
public void testStringArraySingle() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foobar" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("wrapped string should be in result[0]", expected, result);
}
@@ -83,7 +83,7 @@
public void testStringArrayMultiple() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foo", "bar", "baz" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayMultiple", expected, result);
}
@@ -92,7 +92,7 @@
public void testStringArrayNulls() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foo", null, "baz" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayNulls", expected, result);
}
@@ -105,7 +105,7 @@
for (int i = 0; i < expected.length; i++) {
charSeqArray[i] = new SpannableString(expected[i]);
}
- bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
+ bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testCharSequenceArrayMultiple", expected, result);
}
@@ -122,7 +122,7 @@
charSeqArray[i] = new SpannableString(expected[i]);
}
}
- bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
+ bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testMixedCharSequenceArrayList", expected, result);
}
@@ -135,7 +135,7 @@
for (int i = 0; i < expected.length; i++) {
stringArrayList.add(expected[i]);
}
- bundle.putStringArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
+ bundle.putStringArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayList", expected, result);
}
@@ -149,11 +149,24 @@
for (int i = 0; i < expected.length; i++) {
stringArrayList.add(new SpannableString(expected[i]));
}
- bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
+ bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testCharSequenceArrayList", expected, result);
}
+ @Test
+ public void testPeopleArrayList() throws Exception {
+ Bundle bundle = new Bundle();
+ String[] expected = { "name:test" , "tel:1234" };
+ final ArrayList<Notification.Person> arrayList =
+ new ArrayList<>(expected.length);
+ arrayList.add(new Notification.Person().setName("test"));
+ arrayList.add(new Notification.Person().setUri(expected[1]));
+ bundle.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, arrayList);
+ String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
+ assertStringArrayEquals("testPeopleArrayList", expected, result);
+ }
+
private void assertStringArrayEquals(String message, String[] expected, String[] result) {
String expectedString = Arrays.toString(expected);
String resultString = Arrays.toString(result);
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index a1f1810..0cbda28 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -23,7 +23,6 @@
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
-import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
import android.app.usage.UsageStatsManager;
import android.os.SystemClock;
@@ -66,13 +65,7 @@
// History for all users and all packages
private SparseArray<ArrayMap<String,AppUsageHistory>> mIdleHistory = new SparseArray<>();
- private long mLastPeriod = 0;
private static final long ONE_MINUTE = 60 * 1000;
- private static final int HISTORY_SIZE = 100;
- private static final int FLAG_LAST_STATE = 2;
- private static final int FLAG_PARTIAL_ACTIVE = 1;
- private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE
- : 60 * ONE_MINUTE;
@VisibleForTesting
static final String APP_IDLE_FILENAME = "app_idle_stats.xml";
@@ -89,6 +82,10 @@
private static final String ATTR_CURRENT_BUCKET = "appLimitBucket";
// The reason the app was put in the above bucket
private static final String ATTR_BUCKETING_REASON = "bucketReason";
+ // The last time a job was run for this app
+ private static final String ATTR_LAST_RUN_JOB_TIME = "lastJobRunTime";
+ // The time when the forced active state can be overridden.
+ private static final String ATTR_BUCKET_TIMEOUT_TIME = "bucketTimeoutTime";
// device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
@@ -103,8 +100,6 @@
private boolean mScreenOn;
static class AppUsageHistory {
- // Debug
- final byte[] recent = new byte[HISTORY_SIZE];
// Last used time using elapsed timebase
long lastUsedElapsedTime;
// Last used time using screen_on timebase
@@ -118,6 +113,13 @@
String bucketingReason;
// In-memory only, last bucket for which the listeners were informed
int lastInformedBucket;
+ // The last time a job was run for this app, using elapsed timebase
+ long lastJobRunTime;
+ // When should the bucket state timeout, in elapsed timebase, if greater than
+ // lastUsedElapsedTime.
+ // This is used to keep the app in a high bucket regardless of other timeouts and
+ // predictions.
+ long bucketTimeoutTime;
}
AppIdleHistory(File storageDir, long elapsedRealtime) {
@@ -195,81 +197,47 @@
writeScreenOnTime();
}
- public int reportUsage(String packageName, int userId, long elapsedRealtime) {
+ /**
+ * Mark the app as used and update the bucket if necessary. If there is a timeout specified
+ * that's in the future, then the usage event is temporary and keeps the app in the specified
+ * bucket at least until the timeout is reached. This can be used to keep the app in an
+ * elevated bucket for a while until some important task gets to run.
+ * @param packageName
+ * @param userId
+ * @param bucket the bucket to set the app to
+ * @param elapsedRealtime mark as used time if non-zero
+ * @param timeout set the timeout of the specified bucket, if non-zero
+ * @return
+ */
+ public int reportUsage(String packageName, int userId, int bucket, long elapsedRealtime,
+ long timeout) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime, true);
- shiftHistoryToNow(userHistory, elapsedRealtime);
+ if (elapsedRealtime != 0) {
+ appUsageHistory.lastUsedElapsedTime = mElapsedDuration
+ + (elapsedRealtime - mElapsedSnapshot);
+ appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
+ }
- appUsageHistory.lastUsedElapsedTime = mElapsedDuration
- + (elapsedRealtime - mElapsedSnapshot);
- appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
- appUsageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
- if (appUsageHistory.currentBucket > STANDBY_BUCKET_ACTIVE) {
- appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+ if (appUsageHistory.currentBucket > bucket) {
+ appUsageHistory.currentBucket = bucket;
if (DEBUG) {
- Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
+ Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory
+ .currentBucket
+ ", reason=" + appUsageHistory.bucketingReason);
}
+ if (timeout > elapsedRealtime) {
+ // Convert to elapsed timebase
+ appUsageHistory.bucketTimeoutTime = mElapsedDuration + (timeout - mElapsedSnapshot);
+ }
}
appUsageHistory.bucketingReason = REASON_USAGE;
return appUsageHistory.currentBucket;
}
- public int reportMildUsage(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
- AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
- elapsedRealtime, true);
- if (appUsageHistory.currentBucket > STANDBY_BUCKET_WORKING_SET) {
- appUsageHistory.currentBucket = STANDBY_BUCKET_WORKING_SET;
- if (DEBUG) {
- Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
- + ", reason=" + appUsageHistory.bucketingReason);
- }
- }
- // TODO: Should this be a different reason for partial usage?
- appUsageHistory.bucketingReason = REASON_USAGE;
-
- return appUsageHistory.currentBucket;
- }
-
- public void setIdle(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
- AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
- elapsedRealtime, true);
-
- shiftHistoryToNow(userHistory, elapsedRealtime);
-
- appUsageHistory.recent[HISTORY_SIZE - 1] &= ~FLAG_LAST_STATE;
- }
-
- private void shiftHistoryToNow(ArrayMap<String, AppUsageHistory> userHistory,
- long elapsedRealtime) {
- long thisPeriod = elapsedRealtime / PERIOD_DURATION;
- // Has the period switched over? Slide all users' package histories
- if (mLastPeriod != 0 && mLastPeriod < thisPeriod
- && (thisPeriod - mLastPeriod) < HISTORY_SIZE - 1) {
- int diff = (int) (thisPeriod - mLastPeriod);
- final int NUSERS = mIdleHistory.size();
- for (int u = 0; u < NUSERS; u++) {
- userHistory = mIdleHistory.valueAt(u);
- for (AppUsageHistory idleState : userHistory.values()) {
- // Shift left
- System.arraycopy(idleState.recent, diff, idleState.recent, 0,
- HISTORY_SIZE - diff);
- // Replicate last state across the diff
- for (int i = 0; i < diff; i++) {
- idleState.recent[HISTORY_SIZE - i - 1] =
- (byte) (idleState.recent[HISTORY_SIZE - diff - 1] & FLAG_LAST_STATE);
- }
- }
- }
- }
- mLastPeriod = thisPeriod;
- }
-
private ArrayMap<String, AppUsageHistory> getUserHistory(int userId) {
ArrayMap<String, AppUsageHistory> userHistory = mIdleHistory.get(userId);
if (userHistory == null) {
@@ -291,6 +259,7 @@
appUsageHistory.currentBucket = STANDBY_BUCKET_NEVER;
appUsageHistory.bucketingReason = REASON_DEFAULT;
appUsageHistory.lastInformedBucket = -1;
+ appUsageHistory.lastJobRunTime = Long.MIN_VALUE; // long long time ago
userHistory.put(packageName, appUsageHistory);
}
return appUsageHistory;
@@ -338,6 +307,38 @@
}
}
+ /**
+ * Marks the last time a job was run, with the given elapsedRealtime. The time stored is
+ * based on the elapsed timebase.
+ * @param packageName
+ * @param userId
+ * @param elapsedRealtime
+ */
+ public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory appUsageHistory =
+ getPackageHistory(userHistory, packageName, elapsedRealtime, true);
+ appUsageHistory.lastJobRunTime = getElapsedTime(elapsedRealtime);
+ }
+
+ /**
+ * Returns the time since the last job was run for this app. This can be larger than the
+ * current elapsedRealtime, in case it happened before boot or a really large value if no jobs
+ * were ever run.
+ * @param packageName
+ * @param userId
+ * @param elapsedRealtime
+ * @return
+ */
+ public long getTimeSinceLastJobRun(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory appUsageHistory =
+ getPackageHistory(userHistory, packageName, elapsedRealtime, true);
+ // Don't adjust the default, else it'll wrap around to a positive value
+ if (appUsageHistory.lastJobRunTime == Long.MIN_VALUE) return Long.MAX_VALUE;
+ return getElapsedTime(elapsedRealtime) - appUsageHistory.lastJobRunTime;
+ }
+
public int getAppStandbyBucket(String packageName, int userId, long elapsedRealtime) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory =
@@ -473,12 +474,8 @@
Long.parseLong(parser.getAttributeValue(null, ATTR_ELAPSED_IDLE));
appUsageHistory.lastUsedScreenTime =
Long.parseLong(parser.getAttributeValue(null, ATTR_SCREEN_IDLE));
- String lastPredictedTimeString = parser.getAttributeValue(null,
- ATTR_LAST_PREDICTED_TIME);
- if (lastPredictedTimeString != null) {
- appUsageHistory.lastPredictedTime =
- Long.parseLong(lastPredictedTimeString);
- }
+ appUsageHistory.lastPredictedTime = getLongValue(parser,
+ ATTR_LAST_PREDICTED_TIME, 0L);
String currentBucketString = parser.getAttributeValue(null,
ATTR_CURRENT_BUCKET);
appUsageHistory.currentBucket = currentBucketString == null
@@ -486,6 +483,10 @@
: Integer.parseInt(currentBucketString);
appUsageHistory.bucketingReason =
parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
+ appUsageHistory.lastJobRunTime = getLongValue(parser,
+ ATTR_LAST_RUN_JOB_TIME, Long.MIN_VALUE);
+ appUsageHistory.bucketTimeoutTime = getLongValue(parser,
+ ATTR_BUCKET_TIMEOUT_TIME, 0L);
if (appUsageHistory.bucketingReason == null) {
appUsageHistory.bucketingReason = REASON_DEFAULT;
}
@@ -501,6 +502,12 @@
}
}
+ private long getLongValue(XmlPullParser parser, String attrName, long defValue) {
+ String value = parser.getAttributeValue(null, attrName);
+ if (value == null) return defValue;
+ return Long.parseLong(value);
+ }
+
public void writeAppIdleTimes(int userId) {
FileOutputStream fos = null;
AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
@@ -531,6 +538,14 @@
xml.attribute(null, ATTR_CURRENT_BUCKET,
Integer.toString(history.currentBucket));
xml.attribute(null, ATTR_BUCKETING_REASON, history.bucketingReason);
+ if (history.bucketTimeoutTime > 0) {
+ xml.attribute(null, ATTR_BUCKET_TIMEOUT_TIME, Long.toString(history
+ .bucketTimeoutTime));
+ }
+ if (history.lastJobRunTime != Long.MIN_VALUE) {
+ xml.attribute(null, ATTR_LAST_RUN_JOB_TIME, Long.toString(history
+ .lastJobRunTime));
+ }
xml.endTag(null, TAG_PACKAGE);
}
@@ -565,6 +580,10 @@
TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
idpw.print(" lastPredictedTime=");
TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
+ idpw.print(" bucketTimeoutTime=");
+ TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.bucketTimeoutTime, idpw);
+ idpw.print(" lastJobRunTime=");
+ TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastJobRunTime, idpw);
idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.print(" bucket=" + appUsageHistory.currentBucket
+ " reason=" + appUsageHistory.bucketingReason);
@@ -579,21 +598,4 @@
idpw.println();
idpw.decreaseIndent();
}
-
- public void dumpHistory(IndentingPrintWriter idpw, int userId) {
- ArrayMap<String, AppUsageHistory> userHistory = mIdleHistory.get(userId);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- if (userHistory == null) return;
- final int P = userHistory.size();
- for (int p = 0; p < P; p++) {
- final String packageName = userHistory.keyAt(p);
- final byte[] history = userHistory.valueAt(p).recent;
- for (int i = 0; i < HISTORY_SIZE; i++) {
- idpw.print(history[i] == 0 ? '.' : 'A');
- }
- idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
- idpw.print(" " + packageName);
- idpw.println();
- }
- }
}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 9b588fa..2ec218a 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -36,7 +36,6 @@
import android.app.admin.DevicePolicyManager;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageEvents;
-import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
@@ -82,6 +81,8 @@
import java.io.File;
import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -263,8 +264,9 @@
}
if (!packageName.equals(providerPkgName)) {
synchronized (mAppIdleLock) {
- int newBucket = mAppIdleHistory.reportMildUsage(packageName, userId,
- elapsedRealtime);
+ int newBucket = mAppIdleHistory.reportUsage(packageName, userId,
+ STANDBY_BUCKET_ACTIVE, elapsedRealtime,
+ elapsedRealtime + 2 * ONE_HOUR);
maybeInformListeners(packageName, userId, elapsedRealtime,
newBucket);
}
@@ -406,8 +408,10 @@
AppIdleHistory.AppUsageHistory app =
mAppIdleHistory.getAppUsageHistory(packageName,
userId, elapsedRealtime);
- // If the bucket was forced by the developer, leave it alone
- if (REASON_FORCED.equals(app.bucketingReason)) {
+ // If the bucket was forced by the developer or the app is within the
+ // temporary active period, leave it alone.
+ if (REASON_FORCED.equals(app.bucketingReason)
+ || !hasBucketTimeoutPassed(app, elapsedRealtime)) {
continue;
}
boolean predictionLate = false;
@@ -449,6 +453,11 @@
- app.lastPredictedTime > PREDICTION_TIMEOUT;
}
+ private boolean hasBucketTimeoutPassed(AppIdleHistory.AppUsageHistory app,
+ long elapsedRealtime) {
+ return app.bucketTimeoutTime < mAppIdleHistory.getElapsedTime(elapsedRealtime);
+ }
+
private void maybeInformListeners(String packageName, int userId,
long elapsedRealtime, int bucket) {
synchronized (mAppIdleLock) {
@@ -544,11 +553,13 @@
final int newBucket;
if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
- newBucket = mAppIdleHistory.reportMildUsage(event.mPackage, userId,
- elapsedRealtime);
+ newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ STANDBY_BUCKET_WORKING_SET,
+ elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
} else {
newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
- elapsedRealtime);
+ STANDBY_BUCKET_ACTIVE,
+ elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
}
maybeInformListeners(event.mPackage, userId, elapsedRealtime,
@@ -592,6 +603,19 @@
}
}
+ public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.setLastJobRunTime(packageName, userId, elapsedRealtime);
+ }
+ }
+
+ public long getTimeSinceLastJobRun(String packageName, int userId) {
+ final long elapsedRealtime = mInjector.elapsedRealtime();
+ synchronized (mAppIdleLock) {
+ return mAppIdleHistory.getTimeSinceLastJobRun(packageName, userId, elapsedRealtime);
+ }
+ }
+
public void onUserRemoved(int userId) {
synchronized (mAppIdleLock) {
mAppIdleHistory.onUserRemoved(userId);
@@ -805,16 +829,27 @@
AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
userId, elapsedRealtime);
boolean predicted = reason != null && reason.startsWith(REASON_PREDICTED);
+
// Don't allow changing bucket if higher than ACTIVE
if (app.currentBucket < STANDBY_BUCKET_ACTIVE) return;
- // Don't allow prediction to change from or to NEVER
+
+ // Don't allow prediction to change from/to NEVER
if ((app.currentBucket == STANDBY_BUCKET_NEVER
|| newBucket == STANDBY_BUCKET_NEVER)
&& predicted) {
return;
}
+
// If the bucket was forced, don't allow prediction to override
if (app.bucketingReason.equals(REASON_FORCED) && predicted) return;
+
+ // If the bucket is required to stay in a higher state for a specified duration, don't
+ // override unless the duration has passed
+ if (predicted && app.currentBucket < newBucket
+ && !hasBucketTimeoutPassed(app, elapsedRealtime)) {
+ return;
+ }
+
mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
reason);
}
@@ -947,7 +982,10 @@
final PackageInfo pi = packages.get(i);
String packageName = pi.packageName;
if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
- mAppIdleHistory.reportUsage(packageName, userId, elapsedRealtime);
+ // Mark app as used for 4 hours. After that it can timeout to whatever the
+ // past usage pattern was.
+ mAppIdleHistory.reportUsage(packageName, userId, STANDBY_BUCKET_ACTIVE, 0,
+ elapsedRealtime + 4 * ONE_HOUR);
if (isAppSpecial(packageName, UserHandle.getAppId(pi.applicationInfo.uid),
userId)) {
mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
@@ -967,12 +1005,6 @@
.sendToTarget();
}
- void dumpHistory(IndentingPrintWriter idpw, int userId) {
- synchronized (mAppIdleLock) {
- mAppIdleHistory.dumpHistory(idpw, userId);
- }
- }
-
void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
synchronized (mAppIdleLock) {
mAppIdleHistory.dump(idpw, userId, pkg);
@@ -1278,10 +1310,10 @@
synchronized (mAppIdleLock) {
// Default: 24 hours between paroles
- mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL,
+ mAppIdleParoleIntervalMillis = mParser.getDurationMillis(KEY_PAROLE_INTERVAL,
COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
- mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION,
+ mAppIdleParoleDurationMillis = mParser.getDurationMillis(KEY_PAROLE_DURATION,
COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
String screenThresholdsValue = mParser.getString(KEY_SCREEN_TIME_THRESHOLDS, null);
@@ -1308,7 +1340,15 @@
if (thresholds.length == THRESHOLD_BUCKETS.length) {
long[] array = new long[THRESHOLD_BUCKETS.length];
for (int i = 0; i < THRESHOLD_BUCKETS.length; i++) {
- array[i] = Long.parseLong(thresholds[i]);
+ try {
+ if (thresholds[i].startsWith("P") || thresholds[i].startsWith("p")) {
+ array[i] = Duration.parse(thresholds[i]).toMillis();
+ } else {
+ array[i] = Long.parseLong(thresholds[i]);
+ }
+ } catch (NumberFormatException|DateTimeParseException e) {
+ return defaults;
+ }
}
return array;
} else {
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 82f8001..2fec20a 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -49,6 +49,7 @@
import android.provider.Settings;
import android.text.format.DateUtils;
import android.util.ArrayMap;
+import android.util.DataUnit;
import android.util.Slog;
import android.util.SparseLongArray;
@@ -73,7 +74,7 @@
private static final String PROP_VERIFY_STORAGE = "fw.verify_storage";
private static final long DELAY_IN_MILLIS = 30 * DateUtils.SECOND_IN_MILLIS;
- private static final long DEFAULT_QUOTA = 64 * TrafficStats.MB_IN_BYTES;
+ private static final long DEFAULT_QUOTA = DataUnit.MEBIBYTES.toBytes(64);
public static class Lifecycle extends SystemService {
private StorageStatsService mService;
@@ -167,8 +168,11 @@
public boolean isReservedSupported(String volumeUuid, String callingPackage) {
enforcePermission(Binder.getCallingUid(), callingPackage);
- // TODO: implement as part of b/62024591
- return false;
+ if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
+ return SystemProperties.getBoolean(StorageManager.PROP_HAS_RESERVED, false);
+ } else {
+ return false;
+ }
}
@Override
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index cdce448..463a26e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -68,8 +68,6 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -478,7 +476,6 @@
IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
boolean checkin = false;
- boolean history = false;
String pkg = null;
if (args != null) {
@@ -486,11 +483,6 @@
String arg = args[i];
if ("--checkin".equals(arg)) {
checkin = true;
- } else if ("--history".equals(arg)) {
- history = true;
- } else if ("history".equals(arg)) {
- history = true;
- break;
} else if ("flush".equals(arg)) {
flushToDiskLocked();
pw.println("Flushed stats to disk");
@@ -514,9 +506,6 @@
} else {
mUserState.valueAt(i).dump(idpw, pkg);
idpw.println();
- if (history) {
- mAppStandby.dumpHistory(idpw, userId);
- }
}
mAppStandby.dumpUser(idpw, userId, pkg);
idpw.decreaseIndent();
@@ -1021,5 +1010,15 @@
return UsageStatsService.this.queryUsageStats(
userId, intervalType, beginTime, endTime, obfuscateInstantApps);
}
+
+ @Override
+ public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
+ mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime);
+ }
+
+ @Override
+ public long getTimeSinceLastJobRun(String packageName, int userId) {
+ return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
+ }
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 1b057f9..4a7072d 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,6 +16,9 @@
package com.android.server.usb;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -26,6 +29,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -38,6 +42,7 @@
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.os.BatteryManager;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -60,6 +65,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
+import com.android.server.LocalServices;
import java.io.File;
import java.io.FileNotFoundException;
@@ -75,7 +81,7 @@
/**
* UsbDeviceManager manages USB state in device mode.
*/
-public class UsbDeviceManager {
+public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
private static final String TAG = "UsbDeviceManager";
private static final boolean DEBUG = false;
@@ -97,6 +103,12 @@
private static final String USB_STATE_PROPERTY = "sys.usb.state";
/**
+ * The SharedPreference setting per user that stores the screen unlocked functions between
+ * sessions.
+ */
+ private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
+
+ /**
* ro.bootmode value when phone boots into usual Android.
*/
private static final String NORMAL_BOOT = "normal";
@@ -128,6 +140,8 @@
private static final int MSG_UPDATE_CHARGING_STATE = 9;
private static final int MSG_UPDATE_HOST_STATE = 10;
private static final int MSG_LOCALE_CHANGED = 11;
+ private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
+ private static final int MSG_UPDATE_SCREEN_LOCK = 13;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -169,6 +183,7 @@
private Intent mBroadcastedIntent;
private boolean mPendingBootBroadcast;
private static Set<Integer> sBlackListedInterfaces;
+ private SharedPreferences mSettings;
static {
sBlackListedInterfaces = new HashSet<>();
@@ -217,6 +232,31 @@
}
};
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ int userHandle = ActivityManager.getCurrentUser();
+ boolean secure = mContext.getSystemService(KeyguardManager.class)
+ .isDeviceSecure(userHandle);
+ boolean unlocking = mContext.getSystemService(UserManager.class)
+ .isUserUnlockingOrUnlocked(userHandle);
+ if (DEBUG) {
+ Slog.v(TAG, "onKeyguardStateChanged: isShowing:" + isShowing + " secure:" + secure
+ + " unlocking:" + unlocking + " user:" + userHandle);
+ }
+ // We are unlocked when the keyguard is down or non-secure, and user storage is unlocked.
+ mHandler.sendMessage(MSG_UPDATE_SCREEN_LOCK, (isShowing && secure) || !unlocking);
+ }
+
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+ // ignore
+ }
+
+ /** Called when a user is unlocked. */
+ public void onUnlockUser(int userHandle) {
+ onKeyguardStateChanged(false);
+ }
+
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
mContext = context;
@@ -303,6 +343,8 @@
public void systemReady() {
if (DEBUG) Slog.d(TAG, "systemReady");
+ LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
+
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -407,6 +449,14 @@
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
+ private SharedPreferences getPinnedSharedPrefs(Context context) {
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+ context.getUserId(), context.getPackageName()), "shared_prefs"),
+ UsbDeviceManager.class.getSimpleName() + ".xml");
+ return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
+
private final class UsbHandler extends Handler {
// current USB state
@@ -423,11 +473,13 @@
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
private boolean mAdbNotificationShown;
- private int mCurrentUser = UserHandle.USER_NULL;
+ private int mCurrentUser;
private boolean mUsbCharging;
private String mCurrentOemFunctions;
private boolean mHideUsbNotification;
private boolean mSupportsAllCombinations;
+ private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
+ private boolean mScreenLocked;
public UsbHandler(Looper looper) {
super(looper);
@@ -449,6 +501,9 @@
SystemProperties.get(USB_STATE_PROPERTY));
}
+ mCurrentUser = ActivityManager.getCurrentUser();
+ mScreenLocked = true;
+
/*
* Use the normal bootmode persistent prop to maintain state of adb across
* all boot modes.
@@ -653,7 +708,7 @@
private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getDefaultFunctions();
+ functions = getChargingFunctions();
}
functions = applyAdbFunction(functions);
@@ -876,6 +931,14 @@
mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
}
+ private void setScreenUnlockedFunctions() {
+ setEnabledFunctions(mScreenUnlockedFunctions, false,
+ UsbManager.containsFunction(mScreenUnlockedFunctions,
+ UsbManager.USB_FUNCTION_MTP)
+ || UsbManager.containsFunction(mScreenUnlockedFunctions,
+ UsbManager.USB_FUNCTION_PTP));
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -895,7 +958,13 @@
if (mBootCompleted) {
if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)) {
// restore defaults when USB is disconnected
- setEnabledFunctions(null, !mAdbEnabled, false);
+ if (!mScreenLocked
+ && !UsbManager.USB_FUNCTION_NONE.equals(
+ mScreenUnlockedFunctions)) {
+ setScreenUnlockedFunctions();
+ } else {
+ setEnabledFunctions(null, !mAdbEnabled, false);
+ }
}
updateUsbFunctions();
} else {
@@ -978,6 +1047,47 @@
String functions = (String) msg.obj;
setEnabledFunctions(functions, false, msg.arg1 == 1);
break;
+ case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
+ mScreenUnlockedFunctions = (String) msg.obj;
+ SharedPreferences.Editor editor = mSettings.edit();
+ editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
+ mCurrentUser), mScreenUnlockedFunctions);
+ editor.commit();
+ if (!mScreenLocked && !UsbManager.USB_FUNCTION_NONE.equals(
+ mScreenUnlockedFunctions)) {
+ // If the screen is unlocked, also set current functions.
+ setScreenUnlockedFunctions();
+ }
+ break;
+ case MSG_UPDATE_SCREEN_LOCK:
+ if (msg.arg1 == 1 == mScreenLocked) {
+ break;
+ }
+ mScreenLocked = msg.arg1 == 1;
+ if (mSettings == null && !mScreenLocked) {
+ // Shared preferences aren't accessible until the user has been unlocked.
+ mSettings = getPinnedSharedPrefs(mContext);
+ mScreenUnlockedFunctions = mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
+ UsbManager.USB_FUNCTION_NONE);
+ }
+ if (!mBootCompleted) {
+ break;
+ }
+ if (mScreenLocked) {
+ if (!mConnected) {
+ setEnabledFunctions(null, false, false);
+ }
+ } else {
+ if (!UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)
+ && (UsbManager.USB_FUNCTION_ADB.equals(mCurrentFunctions)
+ || (UsbManager.USB_FUNCTION_MTP.equals(mCurrentFunctions)
+ && !mUsbDataUnlocked))) {
+ // Set the screen unlocked functions if current function is charging.
+ setScreenUnlockedFunctions();
+ }
+ }
+ break;
case MSG_UPDATE_USER_RESTRICTIONS:
// Restart the USB stack if USB transfer is enabled but no longer allowed.
final boolean forceRestart = mUsbDataUnlocked
@@ -1001,7 +1111,13 @@
updateUsbStateBroadcastIfNeeded(false);
mPendingBootBroadcast = false;
}
- setEnabledFunctions(null, false, false);
+
+ if (!mScreenLocked
+ && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
+ setScreenUnlockedFunctions();
+ } else {
+ setEnabledFunctions(null, false, false);
+ }
if (mCurrentAccessory != null) {
getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
@@ -1011,16 +1127,15 @@
break;
case MSG_USER_SWITCHED: {
if (mCurrentUser != msg.arg1) {
- // Restart the USB stack and re-apply user restrictions for MTP or PTP.
- if (mUsbDataUnlocked
- && isUsbDataTransferActive()
- && mCurrentUser != UserHandle.USER_NULL) {
- Slog.v(TAG, "Current user switched to " + msg.arg1
- + "; resetting USB host stack for MTP or PTP");
- // avoid leaking sensitive data from previous user
- setEnabledFunctions(null, true, false);
+ if (DEBUG) {
+ Slog.v(TAG, "Current user switched to " + msg.arg1);
}
mCurrentUser = msg.arg1;
+ mScreenLocked = true;
+ mScreenUnlockedFunctions = mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
+ UsbManager.USB_FUNCTION_NONE);
+ setEnabledFunctions(null, false, false);
}
break;
}
@@ -1072,20 +1187,12 @@
titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
} else if (mConnected) {
- if (!mUsbDataUnlocked) {
- if (mSourcePower) {
- titleRes = com.android.internal.R.string.usb_supplying_notification_title;
- id = SystemMessage.NOTE_USB_SUPPLYING;
- } else {
- titleRes = com.android.internal.R.string.usb_charging_notification_title;
- id = SystemMessage.NOTE_USB_CHARGING;
- }
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MTP)) {
+ if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
titleRes = com.android.internal.R.string.usb_mtp_notification_title;
id = SystemMessage.NOTE_USB_MTP;
} else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_PTP)) {
+ UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
titleRes = com.android.internal.R.string.usb_ptp_notification_title;
id = SystemMessage.NOTE_USB_PTP;
} else if (UsbManager.containsFunction(mCurrentFunctions,
@@ -1236,7 +1343,7 @@
}
}
- private String getDefaultFunctions() {
+ private String getChargingFunctions() {
String func = SystemProperties.get(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
// if ADB is enabled, reset functions to ADB
@@ -1253,6 +1360,8 @@
pw.println(" mCurrentFunctions: " + mCurrentFunctions);
pw.println(" mCurrentOemFunctions: " + mCurrentOemFunctions);
pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
+ pw.println(" mScreenUnlockedFunctions: " + mScreenUnlockedFunctions);
+ pw.println(" mScreenLocked: " + mScreenLocked);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked);
@@ -1309,6 +1418,17 @@
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
}
+ /**
+ * Sets the functions which are set when the screen is unlocked.
+ * @param functions Functions to set.
+ */
+ public void setScreenUnlockedFunctions(String functions) {
+ if (DEBUG) {
+ Slog.d(TAG, "setScreenUnlockedFunctions(" + functions + ")");
+ }
+ mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
+ }
+
private void readOemUsbOverrideConfig() {
String[] configList = mContext.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 8554cf7..1a20819 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -87,6 +87,11 @@
public void onStopUser(int userHandle) {
mUsbService.onStopUser(UserHandle.of(userHandle));
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mUsbService.onUnlockUser(userHandle);
+ }
}
private static final String TAG = "UsbService";
@@ -205,6 +210,13 @@
}
}
+ /** Called when a user is unlocked. */
+ public void onUnlockUser(int user) {
+ if (mDeviceManager != null) {
+ mDeviceManager.onUnlockUser(user);
+ }
+ }
+
/* Returns a list of all currently attached USB devices (host mdoe) */
@Override
public void getDeviceList(Bundle devices) {
@@ -392,6 +404,23 @@
}
}
+ @Override
+ public void setScreenUnlockedFunctions(String function) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+ if (!isSupportedCurrentFunction(function)) {
+ Slog.w(TAG, "Caller of setScreenUnlockedFunctions() requested unsupported USB function:"
+ + function);
+ function = UsbManager.USB_FUNCTION_NONE;
+ }
+
+ if (mDeviceManager != null) {
+ mDeviceManager.setScreenUnlockedFunctions(function);
+ } else {
+ throw new IllegalStateException("USB device mode not supported");
+ }
+ }
+
private static boolean isSupportedCurrentFunction(String function) {
if (function == null) return true;
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 3361b5b..83ca470 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -340,24 +340,6 @@
return sSessionManager;
}
- private static MessageDigest sMessageDigest;
-
- public static void initMd5Sum() {
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... args) {
- MessageDigest md;
- try {
- md = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- md = null;
- }
- sMessageDigest = md;
- return null;
- }
- }.execute();
- }
-
public static void setTag(String tag) {
TAG = tag;
DEBUG = isLoggable(android.util.Log.DEBUG);
@@ -425,44 +407,13 @@
/**
* Redact personally identifiable information for production users.
* If we are running in verbose mode, return the original string,
- * and return "****" if we are running on the user build, otherwise
- * return a SHA-1 hash of the input string.
+ * and return "***" otherwise.
*/
public static String pii(Object pii) {
if (pii == null || VERBOSE) {
return String.valueOf(pii);
}
- return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
- }
-
- private static String secureHash(byte[] input) {
- // Refrain from logging user personal information in user build.
- if (USER_BUILD) {
- return "****";
- }
-
- if (sMessageDigest != null) {
- sMessageDigest.reset();
- sMessageDigest.update(input);
- byte[] result = sMessageDigest.digest();
- return encodeHex(result);
- } else {
- return "Uninitialized SHA1";
- }
- }
-
- private static String encodeHex(byte[] bytes) {
- StringBuffer hex = new StringBuffer(bytes.length * 2);
-
- for (int i = 0; i < bytes.length; i++) {
- int byteIntValue = bytes[i] & 0xff;
- if (byteIntValue < 0x10) {
- hex.append("0");
- }
- hex.append(Integer.toString(byteIntValue, 16));
- }
-
- return hex.toString();
+ return "***";
}
private static String getPrefixFromObject(Object obj) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 15355ac..2d1fe50 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -653,7 +653,6 @@
mContext = context;
}
mTelecomServiceOverride = telecomServiceImpl;
- android.telecom.Log.initMd5Sum();
}
/**
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 942ea00..e0b6f61 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2693,6 +2693,7 @@
* but is currently only used for LTE (14) and eHRPD (13).
* <P>Type: INTEGER</P>
*/
+ @Deprecated
public static final String BEARER = "bearer";
/**
@@ -2704,9 +2705,19 @@
* <P>Type: INTEGER</P>
* @hide
*/
+ @Deprecated
public static final String BEARER_BITMASK = "bearer_bitmask";
/**
+ * Radio technology (network type) bitmask.
+ * To check what values can be contained, refer to
+ * {@link android.telephony.TelephonyManager}.
+ * Bitmask for a radio tech R is (1 << (R - 1))
+ * <P>Type: INTEGER</P>
+ */
+ public static final String NETWORK_TYPE_BITMASK = "network_type_bitmask";
+
+ /**
* MVNO type:
* {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
* <P>Type: TEXT</P>
diff --git a/telephony/java/android/telephony/RadioNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
similarity index 95%
rename from telephony/java/android/telephony/RadioNetworkConstants.java
rename to telephony/java/android/telephony/AccessNetworkConstants.java
index 5f5dd82..fc814be 100644
--- a/telephony/java/android/telephony/RadioNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -17,23 +17,23 @@
package android.telephony;
/**
- * Contains radio access network related constants.
+ * Contains access network related constants.
*/
-public final class RadioNetworkConstants {
+public final class AccessNetworkConstants {
- public static final class RadioAccessNetworks {
+ public static final class AccessNetworkType {
public static final int GERAN = 1;
public static final int UTRAN = 2;
public static final int EUTRAN = 3;
- /** @hide */
public static final int CDMA2000 = 4;
+ public static final int IWLAN = 5;
}
/**
* Frenquency bands for GERAN.
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
- public static final class GeranBands {
+ public static final class GeranBand {
public static final int BAND_T380 = 1;
public static final int BAND_T410 = 2;
public static final int BAND_450 = 3;
@@ -54,7 +54,7 @@
* Frenquency bands for UTRAN.
* http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
*/
- public static final class UtranBands {
+ public static final class UtranBand {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
@@ -83,7 +83,7 @@
* Frenquency bands for EUTRAN.
* http://www.etsi.org/deliver/etsi_ts/136100_136199/136101/14.03.00_60/ts_136101v140p.pdf
*/
- public static final class EutranBands {
+ public static final class EutranBand {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6a47d05..fccc2a6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1003,6 +1003,13 @@
public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL =
"always_show_data_rat_icon_bool";
+ /**
+ * Boolean to decide whether to show precise call failed cause to user
+ * @hide
+ */
+ public static final String KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL =
+ "show_precise_failed_cause_bool";
+
// These variables are used by the MMS service and exposed through another API, {@link
// SmsManager}. The variable names and string values are copied from there.
public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -1724,6 +1731,15 @@
*/
public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
+ /**
+ * Determines whether we should show a warning asking the user to check with their carrier
+ * on pricing when the user enabled data roaming.
+ * default to false.
+ * @hide
+ */
+ public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL =
+ "check_pricing_with_carrier_data_roaming_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2007,9 +2023,11 @@
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_IDENTIFY_HIGH_DEFINITION_CALLS_IN_CALL_LOG_BOOL, false);
+ sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
+ sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/CellIdentity.aidl b/telephony/java/android/telephony/CellIdentity.aidl
new file mode 100644
index 0000000..aeee769
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentity.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentity;
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
new file mode 100644
index 0000000..e092d52
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 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.telephony;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * CellIdentity represents the identity of a unique cell. This is the base class for
+ * CellIdentityXxx which represents cell identity for specific network access technology.
+ */
+public abstract class CellIdentity implements Parcelable {
+ /**
+ * Cell identity type
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+ public @interface Type {}
+
+ /**
+ * Unknown cell identity type
+ * @hide
+ */
+ public static final int TYPE_UNKNOWN = 0;
+ /**
+ * GSM cell identity type
+ * @hide
+ */
+ public static final int TYPE_GSM = 1;
+ /**
+ * CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_CDMA = 2;
+ /**
+ * LTE cell identity type
+ * @hide
+ */
+ public static final int TYPE_LTE = 3;
+ /**
+ * WCDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_WCDMA = 4;
+ /**
+ * TDS-CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_TDSCDMA = 5;
+
+ // Log tag
+ /** @hide */
+ protected final String mTag;
+ // Cell identity type
+ /** @hide */
+ protected final int mType;
+ // 3-digit Mobile Country Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMccStr;
+ // 2 or 3-digit Mobile Network Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMncStr;
+
+ /** @hide */
+ protected CellIdentity(String tag, int type, String mcc, String mnc) {
+ mTag = tag;
+ mType = type;
+
+ // Only allow INT_MAX if unknown string mcc/mnc
+ if (mcc == null || mcc.matches("^[0-9]{3}$")) {
+ mMccStr = mcc;
+ } else if (mcc.isEmpty() || mcc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mccStr is empty or unknown, set it as null.
+ mMccStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mcc);
+ }
+
+ if (mnc == null || mnc.matches("^[0-9]{2,3}$")) {
+ mMncStr = mnc;
+ } else if (mnc.isEmpty() || mnc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mncStr is empty or unknown, set it as null.
+ mMncStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mnc);
+ }
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * @hide
+ * @return The type of the cell identity
+ */
+ public @Type int getType() { return mType; }
+
+ /**
+ * Used by child classes for parceling.
+ *
+ * @hide
+ */
+ @CallSuper
+ public void writeToParcel(Parcel dest, int type) {
+ dest.writeInt(type);
+ dest.writeString(mMccStr);
+ dest.writeString(mMncStr);
+ }
+
+ /**
+ * Construct from Parcel
+ * @hide
+ */
+ protected CellIdentity(String tag, int type, Parcel source) {
+ this(tag, type, source.readString(), source.readString());
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<CellIdentity> CREATOR =
+ new Creator<CellIdentity>() {
+ @Override
+ public CellIdentity createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+ case TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
+ case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+ case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+ case TYPE_TDSCDMA: return CellIdentityTdscdma.createFromParcelBody(in);
+ default: throw new IllegalArgumentException("Bad Cell identity Parcel");
+ }
+ }
+
+ @Override
+ public CellIdentity[] newArray(int size) {
+ return new CellIdentity[size];
+ }
+ };
+
+ /** @hide */
+ protected void log(String s) {
+ Rlog.w(mTag, s);
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index ddc938e..2e1d1dc 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique CDMA cell
*/
-public final class CellIdentityCdma implements Parcelable {
-
- private static final String LOG_TAG = "CellSignalStrengthCdma";
+public final class CellIdentityCdma extends CellIdentity {
+ private static final String TAG = CellIdentityCdma.class.getSimpleName();
private static final boolean DBG = false;
// Network Id 0..65535
@@ -60,6 +57,7 @@
* @hide
*/
public CellIdentityCdma() {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = Integer.MAX_VALUE;
mSystemId = Integer.MAX_VALUE;
mBasestationId = Integer.MAX_VALUE;
@@ -81,7 +79,7 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat) {
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
this(nid, sid, bid, lon, lat, null, null);
}
@@ -99,8 +97,9 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat, String alphal,
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
String alphas) {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = nid;
mSystemId = sid;
mBasestationId = bid;
@@ -196,40 +195,33 @@
CellIdentityCdma o = (CellIdentityCdma) other;
- return mNetworkId == o.mNetworkId &&
- mSystemId == o.mSystemId &&
- mBasestationId == o.mBasestationId &&
- mLatitude == o.mLatitude &&
- mLongitude == o.mLongitude &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mNetworkId == o.mNetworkId
+ && mSystemId == o.mSystemId
+ && mBasestationId == o.mBasestationId
+ && mLatitude == o.mLatitude
+ && mLongitude == o.mLongitude
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityCdma:{");
- sb.append(" mNetworkId="); sb.append(mNetworkId);
- sb.append(" mSystemId="); sb.append(mSystemId);
- sb.append(" mBasestationId="); sb.append(mBasestationId);
- sb.append(" mLongitude="); sb.append(mLongitude);
- sb.append(" mLatitude="); sb.append(mLatitude);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mNetworkId=").append(mNetworkId)
+ .append(" mSystemId=").append(mSystemId)
+ .append(" mBasestationId=").append(mBasestationId)
+ .append(" mLongitude=").append(mLongitude)
+ .append(" mLatitude=").append(mLatitude)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_CDMA);
dest.writeInt(mNetworkId);
dest.writeInt(mSystemId);
dest.writeInt(mBasestationId);
@@ -241,10 +233,16 @@
/** Construct from Parcel, type has already been processed */
private CellIdentityCdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readInt(),
- in.readString(), in.readString());
+ super(TAG, TYPE_CDMA, in);
+ mNetworkId = in.readInt();
+ mSystemId = in.readInt();
+ mBasestationId = in.readInt();
+ mLongitude = in.readInt();
+ mLatitude = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityCdma(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -253,7 +251,8 @@
new Creator<CellIdentityCdma>() {
@Override
public CellIdentityCdma createFromParcel(Parcel in) {
- return new CellIdentityCdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -262,10 +261,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityCdma createFromParcelBody(Parcel in) {
+ return new CellIdentityCdma(in);
}
}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 376e6aa..f948f81 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique GSM cell
*/
-public final class CellIdentityGsm implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityGsm";
+public final class CellIdentityGsm extends CellIdentity {
+ private static final String TAG = CellIdentityGsm.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mArfcn;
// 6-bit Base Station Identity Code
private final int mBsic;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityGsm() {
+ super(TAG, TYPE_GSM, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mArfcn = Integer.MAX_VALUE;
mBsic = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -70,7 +62,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid) {
this(lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE,
String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -86,7 +78,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
this(lac, cid, arfcn, bsic, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -103,8 +95,9 @@
*
* @hide
*/
- public CellIdentityGsm (int lac, int cid, int arfcn, int bsic, String mccStr,
+ public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_GSM, mccStr, mncStr);
mLac = lac;
mCid = cid;
mArfcn = arfcn;
@@ -112,31 +105,6 @@
// for inbound parcels
mBsic = (bsic == 0xFF) ? Integer.MAX_VALUE : bsic;
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -237,6 +205,7 @@
/**
+ * @deprecated Primary Scrambling Code is not applicable to GSM.
* @return Integer.MAX_VALUE, undefined for GSM
*/
@Deprecated
@@ -260,58 +229,54 @@
}
CellIdentityGsm o = (CellIdentityGsm) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mArfcn == o.mArfcn &&
- mBsic == o.mBsic &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mArfcn == o.mArfcn
+ && mBsic == o.mBsic
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityGsm:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mArfcn=").append(mArfcn);
- sb.append(" mBsic=").append("0x").append(Integer.toHexString(mBsic));
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mArfcn=").append(mArfcn)
+ .append(" mBsic=").append("0x").append(Integer.toHexString(mBsic))
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_GSM);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mArfcn);
dest.writeInt(mBsic);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityGsm(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_GSM, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mArfcn = in.readInt();
+ mBsic = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityGsm(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -320,7 +285,8 @@
new Creator<CellIdentityGsm>() {
@Override
public CellIdentityGsm createFromParcel(Parcel in) {
- return new CellIdentityGsm(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -329,10 +295,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityGsm createFromParcelBody(Parcel in) {
+ return new CellIdentityGsm(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 6ca5daf6..7f20c8a 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique LTE cell
*/
-public final class CellIdentityLte implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityLte";
+public final class CellIdentityLte extends CellIdentity {
+ private static final String TAG = CellIdentityLte.class.getSimpleName();
private static final boolean DBG = false;
// 28-bit cell identity
@@ -39,10 +36,6 @@
private final int mTac;
// 18-bit Absolute RF Channel Number
private final int mEarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityLte() {
+ super(TAG, TYPE_LTE, null, null);
mCi = Integer.MAX_VALUE;
mPci = Integer.MAX_VALUE;
mTac = Integer.MAX_VALUE;
mEarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -72,7 +64,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
this(ci, pci, tac, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -87,7 +79,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
this(ci, pci, tac, earfcn, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -104,38 +96,13 @@
*
* @hide
*/
- public CellIdentityLte (int ci, int pci, int tac, int earfcn, String mccStr,
+ public CellIdentityLte(int ci, int pci, int tac, int earfcn, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_LTE, mccStr, mncStr);
mCi = ci;
mPci = pci;
mTac = tac;
mEarfcn = earfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -248,58 +215,54 @@
}
CellIdentityLte o = (CellIdentityLte) other;
- return mCi == o.mCi &&
- mPci == o.mPci &&
- mTac == o.mTac &&
- mEarfcn == o.mEarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mCi == o.mCi
+ && mPci == o.mPci
+ && mTac == o.mTac
+ && mEarfcn == o.mEarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityLte:{");
- sb.append(" mCi="); sb.append(mCi);
- sb.append(" mPci="); sb.append(mPci);
- sb.append(" mTac="); sb.append(mTac);
- sb.append(" mEarfcn="); sb.append(mEarfcn);
- sb.append(" mMcc="); sb.append(mMccStr);
- sb.append(" mMnc="); sb.append(mMncStr);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mCi=").append(mCi)
+ .append(" mPci=").append(mPci)
+ .append(" mTac=").append(mTac)
+ .append(" mEarfcn=").append(mEarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_LTE);
dest.writeInt(mCi);
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mEarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityLte(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_LTE, in);
+ mCi = in.readInt();
+ mPci = in.readInt();
+ mTac = in.readInt();
+ mEarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityLte(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -308,7 +271,8 @@
new Creator<CellIdentityLte>() {
@Override
public CellIdentityLte createFromParcel(Parcel in) {
- return new CellIdentityLte(in);
+ in.readInt(); // skip;
+ return createFromParcelBody(in);
}
@Override
@@ -317,10 +281,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityLte createFromParcelBody(Parcel in) {
+ return new CellIdentityLte(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.aidl b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
new file mode 100644
index 0000000..2a182cd
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CellIdentityTdscdma;
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
new file mode 100644
index 0000000..001d19f
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 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.telephony;
+
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * CellIdentity is to represent a unique TD-SCDMA cell
+ */
+public final class CellIdentityTdscdma extends CellIdentity {
+ private static final String TAG = CellIdentityTdscdma.class.getSimpleName();
+ private static final boolean DBG = false;
+
+ // 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+ private final int mLac;
+ // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+ private final int mCid;
+ // 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+ private final int mCpid;
+
+ /**
+ * @hide
+ */
+ public CellIdentityTdscdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
+ mLac = Integer.MAX_VALUE;
+ mCid = Integer.MAX_VALUE;
+ mCpid = Integer.MAX_VALUE;
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
+ this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid);
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code in string format
+ * @param mnc 2 or 3-digit Mobile Network Code in string format
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
+ super(TAG, TYPE_TDSCDMA, mcc, mnc);
+ mLac = lac;
+ mCid = cid;
+ mCpid = cpid;
+ }
+
+ private CellIdentityTdscdma(CellIdentityTdscdma cid) {
+ this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, cid.mCpid);
+ }
+
+ CellIdentityTdscdma copy() {
+ return new CellIdentityTdscdma(this);
+ }
+
+ /**
+ * Get Mobile Country Code in string format
+ * @return Mobile Country Code in string format, null if unknown
+ */
+ public String getMccStr() {
+ return mMccStr;
+ }
+
+ /**
+ * Get Mobile Network Code in string format
+ * @return Mobile Network Code in string format, null if unknown
+ */
+ public String getMncStr() {
+ return mMncStr;
+ }
+
+ /**
+ * @return 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ */
+ public int getLac() {
+ return mLac;
+ }
+
+ /**
+ * @return 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ */
+ public int getCid() {
+ return mCid;
+ }
+
+ /**
+ * @return 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ */
+ public int getCpid() {
+ return mCpid;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mMccStr, mMncStr, mLac, mCid, mCpid);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof CellIdentityTdscdma)) {
+ return false;
+ }
+
+ CellIdentityTdscdma o = (CellIdentityTdscdma) other;
+ return TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && mLac == o.mLac
+ && mCid == o.mCid
+ && mCpid == o.mCpid;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(TAG)
+ .append(":{ mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mCpid=").append(mCpid)
+ .append("}").toString();
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_TDSCDMA);
+ dest.writeInt(mLac);
+ dest.writeInt(mCid);
+ dest.writeInt(mCpid);
+ }
+
+ /** Construct from Parcel, type has already been processed */
+ private CellIdentityTdscdma(Parcel in) {
+ super(TAG, TYPE_TDSCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mCpid = in.readInt();
+
+ if (DBG) log(toString());
+ }
+
+ /** Implement the Parcelable interface */
+ @SuppressWarnings("hiding")
+ public static final Creator<CellIdentityTdscdma> CREATOR =
+ new Creator<CellIdentityTdscdma>() {
+ @Override
+ public CellIdentityTdscdma createFromParcel(Parcel in) {
+ in.readInt(); // skip
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public CellIdentityTdscdma[] newArray(int size) {
+ return new CellIdentityTdscdma[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellIdentityTdscdma createFromParcelBody(Parcel in) {
+ return new CellIdentityTdscdma(in);
+ }
+}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index e4bb4f2..1aa1715 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique UMTS cell
*/
-public final class CellIdentityWcdma implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityWcdma";
+public final class CellIdentityWcdma extends CellIdentity {
+ private static final String TAG = CellIdentityWcdma.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mPsc;
// 16-bit UMTS Absolute RF Channel Number
private final int mUarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityWcdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mPsc = Integer.MAX_VALUE;
mUarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -106,36 +98,11 @@
*/
public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn,
String mccStr, String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_WCDMA, mccStr, mncStr);
mLac = lac;
mCid = cid;
mPsc = psc;
mUarfcn = uarfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -250,58 +217,53 @@
}
CellIdentityWcdma o = (CellIdentityWcdma) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mPsc == o.mPsc &&
- mUarfcn == o.mUarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mPsc == o.mPsc
+ && mUarfcn == o.mUarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityWcdma:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mPsc=").append(mPsc);
- sb.append(" mUarfcn=").append(mUarfcn);
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mPsc=").append(mPsc)
+ .append(" mUarfcn=").append(mUarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_WCDMA);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mPsc);
dest.writeInt(mUarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityWcdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
-
- if (DBG) log("CellIdentityWcdma(Parcel): " + toString());
+ super(TAG, TYPE_WCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mPsc = in.readInt();
+ mUarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -310,7 +272,8 @@
new Creator<CellIdentityWcdma>() {
@Override
public CellIdentityWcdma createFromParcel(Parcel in) {
- return new CellIdentityWcdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -319,10 +282,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityWcdma createFromParcelBody(Parcel in) {
+ return new CellIdentityWcdma(in);
}
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java
index ea503c3..9726569 100644
--- a/telephony/java/android/telephony/NetworkScanRequest.java
+++ b/telephony/java/android/telephony/NetworkScanRequest.java
@@ -143,7 +143,11 @@
int incrementalResultsPeriodicity,
ArrayList<String> mccMncs) {
this.mScanType = scanType;
- this.mSpecifiers = specifiers.clone();
+ if (specifiers != null) {
+ this.mSpecifiers = specifiers.clone();
+ } else {
+ this.mSpecifiers = null;
+ }
this.mSearchPeriodicity = searchPeriodicity;
this.mMaxSearchTime = maxSearchTime;
this.mIncrementalResults = incrementalResults;
@@ -187,7 +191,7 @@
/** Returns the radio access technologies with bands or channels that need to be scanned. */
public RadioAccessSpecifier[] getSpecifiers() {
- return mSpecifiers.clone();
+ return mSpecifiers == null ? null : mSpecifiers.clone();
}
/**
diff --git a/telephony/java/android/telephony/RadioAccessSpecifier.java b/telephony/java/android/telephony/RadioAccessSpecifier.java
index 5412c61..81e7ed0 100644
--- a/telephony/java/android/telephony/RadioAccessSpecifier.java
+++ b/telephony/java/android/telephony/RadioAccessSpecifier.java
@@ -33,7 +33,7 @@
*
* This parameter must be provided or else the scan will be rejected.
*
- * See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
+ * See {@link AccessNetworkConstants.AccessNetworkType} for details.
*/
private int mRadioAccessNetwork;
@@ -43,7 +43,7 @@
* When no specific bands are specified (empty array or null), all the frequency bands
* supported by the modem will be scanned.
*
- * See {@link RadioNetworkConstants} for details.
+ * See {@link AccessNetworkConstants} for details.
*/
private int[] mBands;
@@ -56,7 +56,7 @@
* When no specific channels are specified (empty array or null), all the frequency channels
* supported by the modem will be scanned.
*
- * See {@link RadioNetworkConstants} for details.
+ * See {@link AccessNetworkConstants} for details.
*/
private int[] mChannels;
@@ -72,14 +72,22 @@
*/
public RadioAccessSpecifier(int ran, int[] bands, int[] channels) {
this.mRadioAccessNetwork = ran;
- this.mBands = bands.clone();
- this.mChannels = channels.clone();
+ if (bands != null) {
+ this.mBands = bands.clone();
+ } else {
+ this.mBands = null;
+ }
+ if (channels != null) {
+ this.mChannels = channels.clone();
+ } else {
+ this.mChannels = null;
+ }
}
/**
* Returns the radio access network that needs to be scanned.
*
- * The returned value is define in {@link RadioNetworkConstants.RadioAccessNetworks};
+ * The returned value is define in {@link AccessNetworkConstants.AccessNetworkType};
*/
public int getRadioAccessNetwork() {
return mRadioAccessNetwork;
@@ -88,17 +96,17 @@
/**
* Returns the frequency bands that need to be scanned.
*
- * The returned value is defined in either of {@link RadioNetworkConstants.GeranBands},
- * {@link RadioNetworkConstants.UtranBands} and {@link RadioNetworkConstants.EutranBands}, and
+ * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}, and
* it depends on the returned value of {@link #getRadioAccessNetwork()}.
*/
public int[] getBands() {
- return mBands.clone();
+ return mBands == null ? null : mBands.clone();
}
/** Returns the frequency channels that need to be scanned. */
public int[] getChannels() {
- return mChannels.clone();
+ return mChannels == null ? null : mChannels.clone();
}
public static final Parcelable.Creator<RadioAccessSpecifier> CREATOR =
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 116e711..d4b4b88 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -16,12 +16,15 @@
package android.telephony;
+import android.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Contains phone state and service related information.
*
@@ -105,6 +108,31 @@
/** @hide */
public static final int RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED = 14;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "RIL_RADIO_TECHNOLOGY_" },
+ value = {
+ RIL_RADIO_TECHNOLOGY_UNKNOWN,
+ RIL_RADIO_TECHNOLOGY_GPRS,
+ RIL_RADIO_TECHNOLOGY_EDGE,
+ RIL_RADIO_TECHNOLOGY_UMTS,
+ RIL_RADIO_TECHNOLOGY_IS95A,
+ RIL_RADIO_TECHNOLOGY_IS95B,
+ RIL_RADIO_TECHNOLOGY_1xRTT,
+ RIL_RADIO_TECHNOLOGY_EVDO_0,
+ RIL_RADIO_TECHNOLOGY_EVDO_A,
+ RIL_RADIO_TECHNOLOGY_HSDPA,
+ RIL_RADIO_TECHNOLOGY_HSUPA,
+ RIL_RADIO_TECHNOLOGY_HSPA,
+ RIL_RADIO_TECHNOLOGY_EVDO_B,
+ RIL_RADIO_TECHNOLOGY_EHRPD,
+ RIL_RADIO_TECHNOLOGY_LTE,
+ RIL_RADIO_TECHNOLOGY_HSPAP,
+ RIL_RADIO_TECHNOLOGY_GSM,
+ RIL_RADIO_TECHNOLOGY_TD_SCDMA,
+ RIL_RADIO_TECHNOLOGY_IWLAN,
+ RIL_RADIO_TECHNOLOGY_LTE_CA})
+ public @interface RilRadioTechnology {}
/**
* Available radio technologies for GSM, UMTS and CDMA.
* Duplicates the constants from hardware/radio/include/ril.h
@@ -162,6 +190,12 @@
*/
public static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
+ /**
+ * Number of radio technologies for GSM, UMTS and CDMA.
+ * @hide
+ */
+ private static final int NEXT_RIL_RADIO_TECHNOLOGY = 20;
+
/** @hide */
public static final int RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =
(1 << (RIL_RADIO_TECHNOLOGY_IS95A - 1))
@@ -216,6 +250,11 @@
*/
public static final int ROAMING_TYPE_INTERNATIONAL = 3;
+ /**
+ * Unknown ID. Could be returned by {@link #getNetworkId()} or {@link #getSystemId()}
+ */
+ public static final int UNKNOWN_ID = -1;
+
private int mVoiceRoamingType;
private int mDataRoamingType;
private String mVoiceOperatorAlphaLong;
@@ -1153,7 +1192,8 @@
return getRilDataRadioTechnology();
}
- private int rilRadioTechnologyToNetworkType(int rt) {
+ /** @hide */
+ public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rt) {
switch(rt) {
case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS:
return TelephonyManager.NETWORK_TYPE_GPRS;
@@ -1212,12 +1252,20 @@
return this.mCssIndicator ? 1 : 0;
}
- /** @hide */
+ /**
+ * Get the CDMA NID (Network Identification Number), a number uniquely identifying a network
+ * within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
+ * @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
+ */
public int getNetworkId() {
return this.mNetworkId;
}
- /** @hide */
+ /**
+ * Get the CDMA SID (System Identification Number), a number uniquely identifying a wireless
+ * system. (Defined in 3GPP2 C.S0023 3.4.8)
+ * @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
+ */
public int getSystemId() {
return this.mSystemId;
}
@@ -1300,6 +1348,34 @@
return bearerBitmask;
}
+ /** @hide */
+ public static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
+ if (networkTypeBitmask == 0) {
+ return 0;
+ }
+ int bearerBitmask = 0;
+ for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
+ if (bitmaskHasTech(networkTypeBitmask, rilRadioTechnologyToNetworkType(bearerInt))) {
+ bearerBitmask |= getBitmaskForTech(bearerInt);
+ }
+ }
+ return bearerBitmask;
+ }
+
+ /** @hide */
+ public static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
+ if (bearerBitmask == 0) {
+ return 0;
+ }
+ int networkTypeBitmask = 0;
+ for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
+ if (bitmaskHasTech(bearerBitmask, bearerInt)) {
+ networkTypeBitmask |= getBitmaskForTech(rilRadioTechnologyToNetworkType(bearerInt));
+ }
+ }
+ return networkTypeBitmask;
+ }
+
/**
* Returns a merged ServiceState consisting of the base SS with voice settings from the
* voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned).
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a494799..2fafdf5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -18,10 +18,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.app.BroadcastOptions;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -36,6 +38,7 @@
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.DisplayMetrics;
+import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ISub;
@@ -46,6 +49,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
* SubscriptionManager is the application interface to SubscriptionController
@@ -455,6 +459,39 @@
= "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
/**
+ * Broadcast Action: Request a refresh of the billing relationship plans
+ * between a carrier and a specific subscriber.
+ * <p>
+ * Carrier apps are encouraged to implement this receiver, and the OS will
+ * provide an affordance to request a refresh. This affordance will only be
+ * shown when the carrier app is actively providing subscription plan
+ * information via {@link #setSubscriptionPlans(int, List)}.
+ * <p>
+ * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
+ * the user is interested in.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS
+ = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
+
+ /**
+ * Broadcast Action: The billing relationship plans between a carrier and a
+ * specific subscriber has changed.
+ * <p>
+ * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
+ * changed.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS)
+ public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED
+ = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
+
+ /**
* Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and
* {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription
* which has changed.
@@ -548,7 +585,8 @@
*/
@Deprecated
public static SubscriptionManager from(Context context) {
- return context.getSystemService(SubscriptionManager.class);
+ return (SubscriptionManager) context
+ .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
}
/**
@@ -1636,7 +1674,7 @@
* This method is only accessible to the following narrow set of apps:
* <ul>
* <li>The carrier app for this subscriberId, as determined by
- * {@link TelephonyManager#hasCarrierPrivileges(int)}.
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
* <li>The carrier app explicitly delegated access through
* {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
* </ul>
@@ -1663,7 +1701,7 @@
* This method is only accessible to the following narrow set of apps:
* <ul>
* <li>The carrier app for this subscriberId, as determined by
- * {@link TelephonyManager#hasCarrierPrivileges(int)}.
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
* <li>The carrier app explicitly delegated access through
* {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
* </ul>
@@ -1694,8 +1732,8 @@
}
/**
- * Create an {@link Intent} that will launch towards the carrier app that is
- * currently defining the billing relationship plan through
+ * Create an {@link Intent} that can be launched towards the carrier app
+ * that is currently defining the billing relationship plan through
* {@link #setSubscriptionPlans(int, List)}.
*
* @return ready to launch Intent targeted towards the carrier app, or
@@ -1724,4 +1762,55 @@
return intent;
}
+
+ /** @hide */
+ private @Nullable Intent createRefreshSubscriptionIntent(int subId) {
+ // Bail if no owner
+ final String owner = getSubscriptionPlansOwner(subId);
+ if (owner == null) return null;
+
+ // Bail if no plans
+ final List<SubscriptionPlan> plans = getSubscriptionPlans(subId);
+ if (plans.isEmpty()) return null;
+
+ final Intent intent = new Intent(ACTION_REFRESH_SUBSCRIPTION_PLANS);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setPackage(owner);
+ intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
+
+ // Bail if not implemented
+ if (mContext.getPackageManager().queryBroadcastReceivers(intent, 0).isEmpty()) {
+ return null;
+ }
+
+ return intent;
+ }
+
+ /**
+ * Check if there is a carrier app that is currently defining the billing
+ * relationship plan through {@link #setSubscriptionPlans(int, List)} that
+ * supports refreshing of subscription plans.
+ *
+ * @hide
+ */
+ public boolean isSubscriptionPlansRefreshSupported(int subId) {
+ return createRefreshSubscriptionIntent(subId) != null;
+ }
+
+ /**
+ * Request that the carrier app that is currently defining the billing
+ * relationship plan through {@link #setSubscriptionPlans(int, List)}
+ * refresh its subscription plans.
+ * <p>
+ * If the app is able to successfully update the plans, you'll expect to
+ * receive the {@link #ACTION_SUBSCRIPTION_PLANS_CHANGED} broadcast.
+ *
+ * @hide
+ */
+ public void requestSubscriptionPlansRefresh(int subId) {
+ final Intent intent = createRefreshSubscriptionIntent(subId);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setTemporaryAppWhitelistDuration(TimeUnit.MINUTES.toMillis(1));
+ mContext.sendBroadcast(intent, null, options.toBundle());
+ }
}
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index e42a758..3937201 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -32,6 +32,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Objects;
/**
* Describes a single UICC access rule according to the GlobalPlatform Secure Element Access Control
@@ -205,6 +206,21 @@
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccAccessRule that = (UiccAccessRule) obj;
+ return Arrays.equals(mCertificateHash, that.mCertificateHash)
+ && Objects.equals(mPackageName, that.mPackageName)
+ && mAccessType == that.mAccessType;
+ }
+
+ @Override
public String toString() {
return "cert: " + IccUtils.bytesToHexString(mCertificateHash) + " pkg: " +
mPackageName + " access: " + mAccessType;
diff --git a/telephony/java/android/telephony/data/ApnSetting.aidl b/telephony/java/android/telephony/data/ApnSetting.aidl
new file mode 100644
index 0000000..381e5e8
--- /dev/null
+++ b/telephony/java/android/telephony/data/ApnSetting.aidl
@@ -0,0 +1,18 @@
+/*
+ * 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.telephony.data;
+
+parcelable ApnSetting;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
new file mode 100644
index 0000000..2ab8d4f
--- /dev/null
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -0,0 +1,1370 @@
+/*
+ * 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.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.StringDef;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.hardware.radio.V1_0.ApnTypes;
+import android.net.NetworkUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.net.URL;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A class representing an APN configuration.
+ */
+public class ApnSetting implements Parcelable {
+
+ static final String LOG_TAG = "ApnSetting";
+ private static final boolean VDBG = false;
+
+ private final String mEntryName;
+ private final String mApnName;
+ private final InetAddress mProxy;
+ private final int mPort;
+ private final URL mMmsc;
+ private final InetAddress mMmsProxy;
+ private final int mMmsPort;
+ private final String mUser;
+ private final String mPassword;
+ private final int mAuthType;
+ private final List<String> mTypes;
+ private final int mTypesBitmap;
+ private final int mId;
+ private final String mOperatorNumeric;
+ private final String mProtocol;
+ private final String mRoamingProtocol;
+ private final int mMtu;
+
+ private final boolean mCarrierEnabled;
+ private final int mBearer;
+ private final int mBearerBitmask;
+
+ private final int mProfileId;
+
+ private final boolean mModemCognitive;
+ private final int mMaxConns;
+ private final int mWaitTime;
+ private final int mMaxConnsTime;
+
+ private final String mMvnoType;
+ private final String mMvnoMatchData;
+
+ private boolean mPermanentFailed = false;
+
+ /**
+ * Returns the types bitmap of the APN.
+ *
+ * @return types bitmap of the APN
+ * @hide
+ */
+ public int getTypesBitmap() {
+ return mTypesBitmap;
+ }
+
+ /**
+ * Returns the MTU size of the mobile interface to which the APN connected.
+ *
+ * @return the MTU size of the APN
+ * @hide
+ */
+ public int getMtu() {
+ return mMtu;
+ }
+
+ /**
+ * Radio Access Technology info.
+ * To check what values can hold, refer to ServiceState.java.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the bearer info of the APN
+ * @hide
+ */
+ public int getBearer() {
+ return mBearer;
+ }
+
+ /**
+ * Returns the radio access technology bitmask for this APN.
+ *
+ * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
+ * technologies in ServiceState.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the radio access technology bitmask
+ * @hide
+ */
+ public int getBearerBitmask() {
+ return mBearerBitmask;
+ }
+
+ /**
+ * Returns the profile id to which the APN saved in modem.
+ *
+ * @return the profile id of the APN
+ * @hide
+ */
+ public int getProfileId() {
+ return mProfileId;
+ }
+
+ /**
+ * Returns if the APN setting is to be set in modem.
+ *
+ * @return is the APN setting to be set in modem
+ * @hide
+ */
+ public boolean getModemCognitive() {
+ return mModemCognitive;
+ }
+
+ /**
+ * Returns the max connections of this APN.
+ *
+ * @return the max connections of this APN
+ * @hide
+ */
+ public int getMaxConns() {
+ return mMaxConns;
+ }
+
+ /**
+ * Returns the wait time for retry of the APN.
+ *
+ * @return the wait time for retry of the APN
+ * @hide
+ */
+ public int getWaitTime() {
+ return mWaitTime;
+ }
+
+ /**
+ * Returns the time to limit max connection for the APN.
+ *
+ * @return the time to limit max connection for the APN
+ * @hide
+ */
+ public int getMaxConnsTime() {
+ return mMaxConnsTime;
+ }
+
+ /**
+ * Returns the MVNO data. Examples:
+ * "spn": A MOBILE, BEN NL
+ * "imsi": 302720x94, 2060188
+ * "gid": 4E, 33
+ * "iccid": 898603 etc..
+ *
+ * @return the mvno match data
+ * @hide
+ */
+ public String getMvnoMatchData() {
+ return mMvnoMatchData;
+ }
+
+ /**
+ * Indicates this APN setting is permanently failed and cannot be
+ * retried by the retry manager anymore.
+ *
+ * @return if this APN setting is permanently failed
+ * @hide
+ */
+ public boolean getPermanentFailed() {
+ return mPermanentFailed;
+ }
+
+ /**
+ * Sets if this APN setting is permanently failed.
+ *
+ * @param permanentFailed if this APN setting is permanently failed
+ * @hide
+ */
+ public void setPermanentFailed(boolean permanentFailed) {
+ mPermanentFailed = permanentFailed;
+ }
+
+ /**
+ * Returns the entry name of the APN.
+ *
+ * @return the entry name for the APN
+ */
+ public String getEntryName() {
+ return mEntryName;
+ }
+
+ /**
+ * Returns the name of the APN.
+ *
+ * @return APN name
+ */
+ public String getApnName() {
+ return mApnName;
+ }
+
+ /**
+ * Returns the proxy address of the APN.
+ *
+ * @return proxy address.
+ */
+ public InetAddress getProxy() {
+ return mProxy;
+ }
+
+ /**
+ * Returns the proxy port of the APN.
+ *
+ * @return proxy port
+ */
+ public int getPort() {
+ return mPort;
+ }
+ /**
+ * Returns the MMSC URL of the APN.
+ *
+ * @return MMSC URL.
+ */
+ public URL getMmsc() {
+ return mMmsc;
+ }
+
+ /**
+ * Returns the MMS proxy address of the APN.
+ *
+ * @return MMS proxy address.
+ */
+ public InetAddress getMmsProxy() {
+ return mMmsProxy;
+ }
+
+ /**
+ * Returns the MMS proxy port of the APN.
+ *
+ * @return MMS proxy port
+ */
+ public int getMmsPort() {
+ return mMmsPort;
+ }
+
+ /**
+ * Returns the APN username of the APN.
+ *
+ * @return APN username
+ */
+ public String getUser() {
+ return mUser;
+ }
+
+ /**
+ * Returns the APN password of the APN.
+ *
+ * @return APN password
+ */
+ public String getPassword() {
+ return mPassword;
+ }
+
+ /** @hide */
+ @IntDef({
+ AUTH_TYPE_NONE,
+ AUTH_TYPE_PAP,
+ AUTH_TYPE_CHAP,
+ AUTH_TYPE_PAP_OR_CHAP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AuthType {}
+
+ /**
+ * Returns the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @return authentication type
+ */
+ @AuthType
+ public int getAuthType() {
+ return mAuthType;
+ }
+
+ /** @hide */
+ @StringDef({
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ApnType {}
+
+ /**
+ * Returns the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @return the list of APN types
+ */
+ @ApnType
+ public List<String> getTypes() {
+ return mTypes;
+ }
+
+ /**
+ * Returns the unique database id for this entry.
+ *
+ * @return the unique database id
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the numeric operator ID for the APN. Usually
+ * {@link android.provider.Telephony.Carriers#MCC} +
+ * {@link android.provider.Telephony.Carriers#MNC}.
+ *
+ * @return the numeric operator ID
+ */
+ public String getOperatorNumeric() {
+ return mOperatorNumeric;
+ }
+
+ /** @hide */
+ @StringDef({
+ PROTOCOL_IP,
+ PROTOCOL_IPV6,
+ PROTOCOL_IPV4V6,
+ PROTOCOL_PPP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtocolType {}
+
+ /**
+ * Returns the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @return the protocol
+ */
+ @ProtocolType
+ public String getProtocol() {
+ return mProtocol;
+ }
+
+ /**
+ * Returns the protocol to use to connect to this APN when roaming.
+ *
+ * The syntax is the same as {@link android.provider.Telephony.Carriers#PROTOCOL}.
+ *
+ * @return the roaming protocol
+ */
+ public String getRoamingProtocol() {
+ return mRoamingProtocol;
+ }
+
+ /**
+ * Returns the current status of APN.
+ *
+ * {@code true} : enabled APN.
+ * {@code false} : disabled APN.
+ *
+ * @return the current status
+ */
+ public boolean isEnabled() {
+ return mCarrierEnabled;
+ }
+
+ /** @hide */
+ @StringDef({
+ MVNO_TYPE_SPN,
+ MVNO_TYPE_IMSI,
+ MVNO_TYPE_GID,
+ MVNO_TYPE_ICCID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MvnoType {}
+
+ /**
+ * Returns the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @return the MVNO match type
+ */
+ @MvnoType
+ public String getMvnoType() {
+ return mMvnoType;
+ }
+
+ private ApnSetting(Builder builder) {
+ this.mEntryName = builder.mEntryName;
+ this.mApnName = builder.mApnName;
+ this.mProxy = builder.mProxy;
+ this.mPort = builder.mPort;
+ this.mMmsc = builder.mMmsc;
+ this.mMmsProxy = builder.mMmsProxy;
+ this.mMmsPort = builder.mMmsPort;
+ this.mUser = builder.mUser;
+ this.mPassword = builder.mPassword;
+ this.mAuthType = builder.mAuthType;
+ this.mTypes = (builder.mTypes == null ? new ArrayList<String>() : builder.mTypes);
+ this.mTypesBitmap = builder.mTypesBitmap;
+ this.mId = builder.mId;
+ this.mOperatorNumeric = builder.mOperatorNumeric;
+ this.mProtocol = builder.mProtocol;
+ this.mRoamingProtocol = builder.mRoamingProtocol;
+ this.mMtu = builder.mMtu;
+ this.mCarrierEnabled = builder.mCarrierEnabled;
+ this.mBearer = builder.mBearer;
+ this.mBearerBitmask = builder.mBearerBitmask;
+ this.mProfileId = builder.mProfileId;
+ this.mModemCognitive = builder.mModemCognitive;
+ this.mMaxConns = builder.mMaxConns;
+ this.mWaitTime = builder.mWaitTime;
+ this.mMaxConnsTime = builder.mMaxConnsTime;
+ this.mMvnoType = builder.mMvnoType;
+ this.mMvnoMatchData = builder.mMvnoMatchData;
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
+ String apnName, InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy,
+ int mmsPort, String user, String password, int authType, List<String> types,
+ String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
+ int bearerBitmask, int profileId, boolean modemCognitive, int maxConns,
+ int waitTime, int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
+ return new Builder()
+ .setId(id)
+ .setOperatorNumeric(operatorNumeric)
+ .setEntryName(entryName)
+ .setApnName(apnName)
+ .setProxy(proxy)
+ .setPort(port)
+ .setMmsc(mmsc)
+ .setMmsProxy(mmsProxy)
+ .setMmsPort(mmsPort)
+ .setUser(user)
+ .setPassword(password)
+ .setAuthType(authType)
+ .setTypes(types)
+ .setProtocol(protocol)
+ .setRoamingProtocol(roamingProtocol)
+ .setCarrierEnabled(carrierEnabled)
+ .setBearer(bearer)
+ .setBearerBitmask(bearerBitmask)
+ .setProfileId(profileId)
+ .setModemCognitive(modemCognitive)
+ .setMaxConns(maxConns)
+ .setWaitTime(waitTime)
+ .setMaxConnsTime(maxConnsTime)
+ .setMtu(mtu)
+ .setMvnoType(mvnoType)
+ .setMvnoMatchData(mvnoMatchData)
+ .build();
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(Cursor cursor) {
+ String[] types = parseTypes(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
+
+ return makeApnSetting(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+ URLFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+ Arrays.asList(types),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.BEARER_BITMASK)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MAX_CONNS_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_MATCH_DATA)));
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(ApnSetting apn) {
+ return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
+ apn.mProxy, apn.mPort, apn.mMmsc, apn.mMmsProxy, apn.mMmsPort, apn.mUser,
+ apn.mPassword, apn.mAuthType, apn.mTypes, apn.mProtocol, apn.mRoamingProtocol,
+ apn.mCarrierEnabled, apn.mBearer, apn.mBearerBitmask, apn.mProfileId,
+ apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime, apn.mMaxConnsTime, apn.mMtu,
+ apn.mMvnoType, apn.mMvnoMatchData);
+ }
+
+ /** @hide */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[ApnSettingV3] ")
+ .append(mEntryName)
+ .append(", ").append(mId)
+ .append(", ").append(mOperatorNumeric)
+ .append(", ").append(mApnName)
+ .append(", ").append(inetAddressToString(mProxy))
+ .append(", ").append(URLToString(mMmsc))
+ .append(", ").append(inetAddressToString(mMmsProxy))
+ .append(", ").append(portToString(mMmsPort))
+ .append(", ").append(portToString(mPort))
+ .append(", ").append(mAuthType).append(", ");
+ for (int i = 0; i < mTypes.size(); i++) {
+ sb.append(mTypes.get(i));
+ if (i < mTypes.size() - 1) {
+ sb.append(" | ");
+ }
+ }
+ sb.append(", ").append(mProtocol);
+ sb.append(", ").append(mRoamingProtocol);
+ sb.append(", ").append(mCarrierEnabled);
+ sb.append(", ").append(mBearer);
+ sb.append(", ").append(mBearerBitmask);
+ sb.append(", ").append(mProfileId);
+ sb.append(", ").append(mModemCognitive);
+ sb.append(", ").append(mMaxConns);
+ sb.append(", ").append(mWaitTime);
+ sb.append(", ").append(mMaxConnsTime);
+ sb.append(", ").append(mMtu);
+ sb.append(", ").append(mMvnoType);
+ sb.append(", ").append(mMvnoMatchData);
+ sb.append(", ").append(mPermanentFailed);
+ return sb.toString();
+ }
+
+ /**
+ * Returns true if there are MVNO params specified.
+ * @hide
+ */
+ public boolean hasMvnoParams() {
+ return !TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData);
+ }
+
+ /** @hide */
+ public boolean canHandleType(String type) {
+ if (!mCarrierEnabled) return false;
+ boolean wildcardable = true;
+ if (TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
+ for (String t : mTypes) {
+ // DEFAULT handles all, and HIPRI is handled by DEFAULT
+ if (t.equalsIgnoreCase(type)
+ || (wildcardable && t.equalsIgnoreCase(TYPE_ALL))
+ || (t.equalsIgnoreCase(TYPE_DEFAULT)
+ && type.equalsIgnoreCase(TYPE_HIPRI))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // check whether the types of two APN same (even only one type of each APN is same)
+ private boolean typeSameAny(ApnSetting first, ApnSetting second) {
+ if (VDBG) {
+ StringBuilder apnType1 = new StringBuilder(first.mApnName + ": ");
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ apnType1.append(first.mTypes.get(index1));
+ apnType1.append(",");
+ }
+
+ StringBuilder apnType2 = new StringBuilder(second.mApnName + ": ");
+ for (int index1 = 0; index1 < second.mTypes.size(); index1++) {
+ apnType2.append(second.mTypes.get(index1));
+ apnType2.append(",");
+ }
+ Rlog.d(LOG_TAG, "APN1: is " + apnType1);
+ Rlog.d(LOG_TAG, "APN2: is " + apnType2);
+ }
+
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ for (int index2 = 0; index2 < second.mTypes.size(); index2++) {
+ if (first.mTypes.get(index1).equals(ApnSetting.TYPE_ALL)
+ || second.mTypes.get(index2).equals(ApnSetting.TYPE_ALL)
+ || first.mTypes.get(index1).equals(second.mTypes.get(index2))) {
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
+ return true;
+ }
+ }
+ }
+
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
+ return false;
+ }
+
+ // TODO - if we have this function we should also have hashCode.
+ // Also should handle changes in type order and perhaps case-insensitivity
+ /** @hide */
+ public boolean equals(Object o) {
+ if (o instanceof ApnSetting == false) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort,other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mBearer, other.mBearer)
+ && Objects.equals(mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Compare two APN settings
+ *
+ * Note: This method does not compare 'id', 'bearer', 'bearerBitmask'. We only use this for
+ * determining if tearing a data call is needed when conditions change. See
+ * cleanUpConnectionsOnUpdatedApns in DcTracker.
+ *
+ * @param o the other object to compare
+ * @param isDataRoaming True if the device is on data roaming
+ * @return True if the two APN settings are same
+ * @hide
+ */
+ public boolean equals(Object o, boolean isDataRoaming) {
+ if (!(o instanceof ApnSetting)) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort, other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Check if neither mention DUN and are substantially similar
+ *
+ * @param other The other APN settings to compare
+ * @return True if two APN settings are similar
+ * @hide
+ */
+ public boolean similar(ApnSetting other) {
+ return (!this.canHandleType(TYPE_DUN)
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && !typeSameAny(this, other)
+ && xorEqualsInetAddress(this.mProxy, other.mProxy)
+ && xorEqualsPort(this.mPort, other.mPort)
+ && xorEquals(this.mProtocol, other.mProtocol)
+ && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && xorEqualsURL(this.mMmsc, other.mMmsc)
+ && xorEqualsInetAddress(this.mMmsProxy, other.mMmsProxy)
+ && xorEqualsPort(this.mMmsPort, other.mMmsPort));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEquals(String first, String second) {
+ return (Objects.equals(first, second)
+ || TextUtils.isEmpty(first)
+ || TextUtils.isEmpty(second));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsInetAddress(InetAddress first, InetAddress second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsURL(URL first, URL second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsPort(int first, int second) {
+ return first == -1 || second == -1 || Objects.equals(first, second);
+ }
+
+ // Helper function to convert APN string into a 32-bit bitmask.
+ private static int getApnBitmask(String apn) {
+ switch (apn) {
+ case TYPE_DEFAULT: return ApnTypes.DEFAULT;
+ case TYPE_MMS: return ApnTypes.MMS;
+ case TYPE_SUPL: return ApnTypes.SUPL;
+ case TYPE_DUN: return ApnTypes.DUN;
+ case TYPE_HIPRI: return ApnTypes.HIPRI;
+ case TYPE_FOTA: return ApnTypes.FOTA;
+ case TYPE_IMS: return ApnTypes.IMS;
+ case TYPE_CBS: return ApnTypes.CBS;
+ case TYPE_IA: return ApnTypes.IA;
+ case TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
+ case TYPE_ALL: return ApnTypes.ALL;
+ default: return ApnTypes.NONE;
+ }
+ }
+
+ private String deParseTypes(List<String> types) {
+ if (types == null) {
+ return null;
+ }
+ return TextUtils.join(",", types);
+ }
+
+ /** @hide */
+ // Called by DPM.
+ public ContentValues toContentValues() {
+ ContentValues apnValue = new ContentValues();
+ if (mOperatorNumeric != null) {
+ apnValue.put(Telephony.Carriers.NUMERIC, mOperatorNumeric);
+ }
+ if (mEntryName != null) {
+ apnValue.put(Telephony.Carriers.NAME, mEntryName);
+ }
+ if (mApnName != null) {
+ apnValue.put(Telephony.Carriers.APN, mApnName);
+ }
+ if (mProxy != null) {
+ apnValue.put(Telephony.Carriers.PROXY, inetAddressToString(mProxy));
+ }
+ apnValue.put(Telephony.Carriers.PORT, portToString(mPort));
+ if (mMmsc != null) {
+ apnValue.put(Telephony.Carriers.MMSC, URLToString(mMmsc));
+ }
+ apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsPort));
+ if (mMmsProxy != null) {
+ apnValue.put(Telephony.Carriers.MMSPROXY, inetAddressToString(mMmsProxy));
+ }
+ if (mUser != null) {
+ apnValue.put(Telephony.Carriers.USER, mUser);
+ }
+ if (mPassword != null) {
+ apnValue.put(Telephony.Carriers.PASSWORD, mPassword);
+ }
+ apnValue.put(Telephony.Carriers.AUTH_TYPE, mAuthType);
+ String apnType = deParseTypes(mTypes);
+ if (apnType != null) {
+ apnValue.put(Telephony.Carriers.TYPE, apnType);
+ }
+ if (mProtocol != null) {
+ apnValue.put(Telephony.Carriers.PROTOCOL, mProtocol);
+ }
+ if (mRoamingProtocol != null) {
+ apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL, mRoamingProtocol);
+ }
+ apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
+ // networkTypeBit.
+ apnValue.put(Telephony.Carriers.BEARER_BITMASK, mBearerBitmask);
+ if (mMvnoType != null) {
+ apnValue.put(Telephony.Carriers.MVNO_TYPE, mMvnoType);
+ }
+
+ return apnValue;
+ }
+
+ /**
+ * @param types comma delimited list of APN types
+ * @return array of APN types
+ * @hide
+ */
+ public static String[] parseTypes(String types) {
+ String[] result;
+ // If unset, set to DEFAULT.
+ if (TextUtils.isEmpty(types)) {
+ result = new String[1];
+ result[0] = TYPE_ALL;
+ } else {
+ result = types.split(",");
+ }
+ return result;
+ }
+
+ private static URL URLFromString(String url) {
+ try {
+ return TextUtils.isEmpty(url) ? null : new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(LOG_TAG, "Can't parse URL from string.");
+ return null;
+ }
+ }
+
+ private static String URLToString(URL url) {
+ return url == null ? "" : url.toString();
+ }
+
+ private static InetAddress inetAddressFromString(String inetAddress) {
+ if (TextUtils.isEmpty(inetAddress)) {
+ return null;
+ }
+ try {
+ return InetAddress.getByName(inetAddress);
+ } catch (UnknownHostException e) {
+ Log.e(LOG_TAG, "Can't parse InetAddress from string: unknown host.");
+ return null;
+ }
+ }
+
+ private static String inetAddressToString(InetAddress inetAddress) {
+ if (inetAddress == null) {
+ return null;
+ }
+ return TextUtils.isEmpty(inetAddress.getHostName())
+ ? inetAddress.getHostAddress() : inetAddress.getHostName();
+ }
+
+ private static int portFromString(String strPort) {
+ int port = -1;
+ if (!TextUtils.isEmpty(strPort)) {
+ try {
+ port = Integer.parseInt(strPort);
+ } catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Can't parse port from String");
+ }
+ }
+ return port;
+ }
+
+ private static String portToString(int port) {
+ return port == -1 ? "" : Integer.toString(port);
+ }
+
+ // Implement Parcelable.
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mId);
+ dest.writeString(mOperatorNumeric);
+ dest.writeString(mEntryName);
+ dest.writeString(mApnName);
+ dest.writeValue(mProxy);
+ dest.writeInt(mPort);
+ dest.writeValue(mMmsc);
+ dest.writeValue(mMmsProxy);
+ dest.writeInt(mMmsPort);
+ dest.writeString(mUser);
+ dest.writeString(mPassword);
+ dest.writeInt(mAuthType);
+ dest.writeStringArray(mTypes.toArray(new String[0]));
+ dest.writeString(mProtocol);
+ dest.writeString(mRoamingProtocol);
+ dest.writeInt(mCarrierEnabled ? 1: 0);
+ dest.writeString(mMvnoType);
+ }
+
+ private static ApnSetting readFromParcel(Parcel in) {
+ return makeApnSetting(in.readInt(), in.readString(), in.readString(), in.readString(),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), (URL)in.readValue(URL.class.getClassLoader()),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), in.readString(), in.readString(), in.readInt(),
+ Arrays.asList(in.readStringArray()), in.readString(), in.readString(),
+ in.readInt() > 0, 0, 0, 0, false, 0, 0, 0, 0, in.readString(), null);
+ }
+
+ public static final Parcelable.Creator<ApnSetting> CREATOR =
+ new Parcelable.Creator<ApnSetting>() {
+ @Override
+ public ApnSetting createFromParcel(Parcel in) {
+ return readFromParcel(in);
+ }
+
+ @Override
+ public ApnSetting[] newArray(int size) {
+ return new ApnSetting[size];
+ }
+ };
+
+ /**
+ * APN types for data connections. These are usage categories for an APN
+ * entry. One APN entry may support multiple APN types, eg, a single APN
+ * may service regular internet traffic ("default") as well as MMS-specific
+ * connections.<br/>
+ * ALL is a special type to indicate that this APN entry can
+ * service all data connections.
+ */
+ public static final String TYPE_ALL = "*";
+ /** APN type for default data traffic */
+ public static final String TYPE_DEFAULT = "default";
+ /** APN type for MMS traffic */
+ public static final String TYPE_MMS = "mms";
+ /** APN type for SUPL assisted GPS */
+ public static final String TYPE_SUPL = "supl";
+ /** APN type for DUN traffic */
+ public static final String TYPE_DUN = "dun";
+ /** APN type for HiPri traffic */
+ public static final String TYPE_HIPRI = "hipri";
+ /** APN type for FOTA */
+ public static final String TYPE_FOTA = "fota";
+ /** APN type for IMS */
+ public static final String TYPE_IMS = "ims";
+ /** APN type for CBS */
+ public static final String TYPE_CBS = "cbs";
+ /** APN type for IA Initial Attach APN */
+ public static final String TYPE_IA = "ia";
+ /** APN type for Emergency PDN. This is not an IA apn, but is used
+ * for access to carrier services in an emergency call situation. */
+ public static final String TYPE_EMERGENCY = "emergency";
+ /**
+ * Array of all APN types
+ *
+ * @hide
+ */
+ public static final String[] ALL_TYPES = {
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ };
+
+ // Possible values for authentication types.
+ public static final int AUTH_TYPE_NONE = 0;
+ public static final int AUTH_TYPE_PAP = 1;
+ public static final int AUTH_TYPE_CHAP = 2;
+ public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
+
+ // Possible values for protocol.
+ public static final String PROTOCOL_IP = "IP";
+ public static final String PROTOCOL_IPV6 = "IPV6";
+ public static final String PROTOCOL_IPV4V6 = "IPV4V6";
+ public static final String PROTOCOL_PPP = "PPP";
+
+ // Possible values for MVNO type.
+ public static final String MVNO_TYPE_SPN = "spn";
+ public static final String MVNO_TYPE_IMSI = "imsi";
+ public static final String MVNO_TYPE_GID = "gid";
+ public static final String MVNO_TYPE_ICCID = "iccid";
+
+ public static class Builder{
+ private String mEntryName;
+ private String mApnName;
+ private InetAddress mProxy;
+ private int mPort = -1;
+ private URL mMmsc;
+ private InetAddress mMmsProxy;
+ private int mMmsPort = -1;
+ private String mUser;
+ private String mPassword;
+ private int mAuthType;
+ private List<String> mTypes;
+ private int mTypesBitmap;
+ private int mId;
+ private String mOperatorNumeric;
+ private String mProtocol;
+ private String mRoamingProtocol;
+ private int mMtu;
+ private boolean mCarrierEnabled;
+ private int mBearer;
+ private int mBearerBitmask;
+ private int mProfileId;
+ private boolean mModemCognitive;
+ private int mMaxConns;
+ private int mWaitTime;
+ private int mMaxConnsTime;
+ private String mMvnoType;
+ private String mMvnoMatchData;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Set the MTU size of the mobile interface to which the APN connected.
+ *
+ * @param mtu the MTU size to set for the APN
+ * @hide
+ */
+ public Builder setMtu(int mtu) {
+ this.mMtu = mtu;
+ return this;
+ }
+
+ /**
+ * Sets bearer info.
+ *
+ * @param bearer the bearer info to set for the APN
+ * @hide
+ */
+ public Builder setBearer(int bearer) {
+ this.mBearer = bearer;
+ return this;
+ }
+
+ /**
+ * Sets the radio access technology bitmask for this APN.
+ *
+ * @param bearerBitmask the radio access technology bitmask to set for this APN
+ * @hide
+ */
+ public Builder setBearerBitmask(int bearerBitmask) {
+ this.mBearerBitmask = bearerBitmask;
+ return this;
+ }
+
+ /**
+ * Sets the profile id to which the APN saved in modem.
+ *
+ * @param profileId the profile id to set for the APN
+ * @hide
+ */
+ public Builder setProfileId(int profileId) {
+ this.mProfileId = profileId;
+ return this;
+ }
+
+ /**
+ * Sets if the APN setting is to be set in modem.
+ *
+ * @param modemCognitive if the APN setting is to be set in modem
+ * @hide
+ */
+ public Builder setModemCognitive(boolean modemCognitive) {
+ this.mModemCognitive = modemCognitive;
+ return this;
+ }
+
+ /**
+ * Sets the max connections of this APN.
+ *
+ * @param maxConns the max connections of this APN
+ * @hide
+ */
+ public Builder setMaxConns(int maxConns) {
+ this.mMaxConns = maxConns;
+ return this;
+ }
+
+ /**
+ * Sets the wait time for retry of the APN.
+ *
+ * @param waitTime the wait time for retry of the APN
+ * @hide
+ */
+ public Builder setWaitTime(int waitTime) {
+ this.mWaitTime = waitTime;
+ return this;
+ }
+
+ /**
+ * Sets the time to limit max connection for the APN.
+ *
+ * @param maxConnsTime the time to limit max connection for the APN
+ * @hide
+ */
+ public Builder setMaxConnsTime(int maxConnsTime) {
+ this.mMaxConnsTime = maxConnsTime;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match data for the APN.
+ *
+ * @param mvnoMatchData the MVNO match data for the APN
+ * @hide
+ */
+ public Builder setMvnoMatchData(String mvnoMatchData) {
+ this.mMvnoMatchData = mvnoMatchData;
+ return this;
+ }
+
+ /**
+ * Sets the entry name of the APN.
+ *
+ * @param entryName the entry name to set for the APN
+ */
+ public Builder setEntryName(String entryName) {
+ this.mEntryName = entryName;
+ return this;
+ }
+
+ /**
+ * Sets the name of the APN.
+ *
+ * @param apnName the name to set for the APN
+ */
+ public Builder setApnName(String apnName) {
+ this.mApnName = apnName;
+ return this;
+ }
+
+ /**
+ * Sets the proxy address of the APN.
+ *
+ * @param proxy the proxy address to set for the APN
+ */
+ public Builder setProxy(InetAddress proxy) {
+ this.mProxy = proxy;
+ return this;
+ }
+
+ /**
+ * Sets the proxy port of the APN.
+ *
+ * @param port the proxy port to set for the APN
+ */
+ public Builder setPort(int port) {
+ this.mPort = port;
+ return this;
+ }
+
+ /**
+ * Sets the MMSC URL of the APN.
+ *
+ * @param mmsc the MMSC URL to set for the APN
+ */
+ public Builder setMmsc(URL mmsc) {
+ this.mMmsc = mmsc;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy address of the APN.
+ *
+ * @param mmsProxy the MMS proxy address to set for the APN
+ */
+ public Builder setMmsProxy(InetAddress mmsProxy) {
+ this.mMmsProxy = mmsProxy;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy port of the APN.
+ *
+ * @param mmsPort the MMS proxy port to set for the APN
+ */
+ public Builder setMmsPort(int mmsPort) {
+ this.mMmsPort = mmsPort;
+ return this;
+ }
+
+ /**
+ * Sets the APN username of the APN.
+ *
+ * @param user the APN username to set for the APN
+ */
+ public Builder setUser(String user) {
+ this.mUser = user;
+ return this;
+ }
+
+ /**
+ * Sets the APN password of the APN.
+ *
+ * @see android.provider.Telephony.Carriers#PASSWORD
+ * @param password the APN password to set for the APN
+ */
+ public Builder setPassword(String password) {
+ this.mPassword = password;
+ return this;
+ }
+
+ /**
+ * Sets the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @param authType the authentication type to set for the APN
+ */
+ public Builder setAuthType(@AuthType int authType) {
+ this.mAuthType = authType;
+ return this;
+ }
+
+ /**
+ * Sets the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @param types the list of APN types to set for the APN
+ */
+ public Builder setTypes(@ApnType List<String> types) {
+ this.mTypes = types;
+ int apnBitmap = 0;
+ for (int i = 0; i < mTypes.size(); i++) {
+ mTypes.set(i, mTypes.get(i).toLowerCase());
+ apnBitmap |= getApnBitmask(mTypes.get(i));
+ }
+ this.mTypesBitmap = apnBitmap;
+ return this;
+ }
+
+ /**
+ * Sets the unique database id for this entry.
+ *
+ * @param id the unique database id to set for this entry
+ */
+ public Builder setId(int id) {
+ this.mId = id;
+ return this;
+ }
+
+ /**
+ * Set the numeric operator ID for the APN.
+ *
+ * @param operatorNumeric the numeric operator ID to set for this entry
+ */
+ public Builder setOperatorNumeric(String operatorNumeric) {
+ this.mOperatorNumeric = operatorNumeric;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @param protocol the protocol to set to use to connect to this APN
+ */
+ public Builder setProtocol(@ProtocolType String protocol) {
+ this.mProtocol = protocol;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN when roaming.
+ *
+ * @param roamingProtocol the protocol to set to use to connect to this APN when roaming
+ */
+ public Builder setRoamingProtocol(String roamingProtocol) {
+ this.mRoamingProtocol = roamingProtocol;
+ return this;
+ }
+
+ /**
+ * Sets the current status of APN.
+ *
+ * @param carrierEnabled the current status to set for this APN
+ */
+ public Builder setCarrierEnabled(boolean carrierEnabled) {
+ this.mCarrierEnabled = carrierEnabled;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @param mvnoType the MVNO match type to set for this APN
+ */
+ public Builder setMvnoType(@MvnoType String mvnoType) {
+ this.mMvnoType = mvnoType;
+ return this;
+ }
+
+ public ApnSetting build() {
+ return new ApnSetting(this);
+ }
+ }
+}
+
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 176057d..2534327 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -60,6 +60,20 @@
public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+
+ /**
+ * Broadcast Action: The eUICC OTA status is changed.
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ * TODO(b/35851809): Make this a SystemApi.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_OTA_STATUS_CHANGED
+ = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+
/**
* Intent action to provision an embedded subscription.
*
@@ -251,8 +265,8 @@
*
* @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready,
* {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
+ * TODO(b/35851809): Make this a SystemApi.
*/
- @SystemApi
public int getOtaStatus() {
if (!isEnabled()) {
return EUICC_OTA_STATUS_UNAVAILABLE;
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 30c9af1..0088962 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -63,6 +63,26 @@
jarjar_rules: "jarjar-rules.txt",
}
+// Build the android.test.base-minus-junit library
+// ===============================================
+// This contains the android.test classes from android.test.base plus
+// the com.android.internal.util.Predicate[s] classes. This is only
+// intended for inclusion in the android.test.legacy static library and
+// must not be used elsewhere.
+java_library_static {
+ name: "android.test.base-minus-junit",
+
+ srcs: [
+ "src/android/**/*.java",
+ "src/com/**/*.java",
+ ],
+
+ sdk_version: "current",
+ libs: [
+ "junit",
+ ],
+}
+
// Build the legacy-android-test library
// =====================================
// This contains the android.test classes that were in Android API level 25,
diff --git a/test-base/Android.mk b/test-base/Android.mk
index 5e5d040..8613854 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -112,17 +112,6 @@
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-# Build the legacy.test.stubs library
-# ===================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := legacy.test.stubs
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := android.test.base.stubs
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
ifeq ($(HOST_OS),linux)
# Build the legacy-performance-test-hostdex library
# =================================================
diff --git a/test-mock/api/android-test-mock-current.txt b/test-mock/api/android-test-mock-current.txt
index 48a1f80..07acfef 100644
--- a/test-mock/api/android-test-mock-current.txt
+++ b/test-mock/api/android-test-mock-current.txt
@@ -1,5 +1,9 @@
package android.test.mock {
+ public deprecated class MockAccountManager {
+ method public static android.accounts.AccountManager newMockAccountManager(android.content.Context);
+ }
+
public deprecated class MockApplication extends android.app.Application {
ctor public MockApplication();
}
@@ -9,6 +13,7 @@
ctor public MockContentProvider(android.content.Context);
ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>);
+ method public static deprecated void attachInfoForTesting(android.content.ContentProvider, android.content.Context, android.content.pm.ProviderInfo);
method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
method public java.lang.String getType(android.net.Uri);
method public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
@@ -289,5 +294,9 @@
method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
}
+ public deprecated class MockService {
+ method public static <T extends android.app.Service> void attachForTesting(android.app.Service, android.content.Context, java.lang.String, android.app.Application);
+ }
+
}
diff --git a/test-mock/src/android/test/mock/MockAccountManager.java b/test-mock/src/android/test/mock/MockAccountManager.java
new file mode 100644
index 0000000..c9b4c7b
--- /dev/null
+++ b/test-mock/src/android/test/mock/MockAccountManager.java
@@ -0,0 +1,119 @@
+/*
+ * 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.test.mock;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OnAccountsUpdateListener;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.os.Handler;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A mock {@link android.accounts.AccountManager} class.
+ *
+ * <p>Provided for use by {@code android.test.IsolatedContext}.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}
+ * tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+public class MockAccountManager {
+
+ /**
+ * Create a new mock {@link AccountManager} instance.
+ *
+ * @param context the {@link Context} to which the returned object belongs.
+ * @return the new instance.
+ */
+ public static AccountManager newMockAccountManager(Context context) {
+ return new MockAccountManagerImpl(context);
+ }
+
+ private MockAccountManager() {
+ }
+
+ private static class MockAccountManagerImpl extends AccountManager {
+
+ MockAccountManagerImpl(Context context) {
+ super(context, null /* IAccountManager */, null /* handler */);
+ }
+
+ public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener,
+ Handler handler, boolean updateImmediately) {
+ // do nothing
+ }
+
+ public Account[] getAccounts() {
+ return new Account[] {};
+ }
+
+ public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
+ final String type, final String[] features,
+ AccountManagerCallback<Account[]> callback, Handler handler) {
+ return new MockAccountManagerFuture<Account[]>(new Account[0]);
+ }
+
+ public String blockingGetAuthToken(Account account, String authTokenType,
+ boolean notifyAuthFailure)
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ return null;
+ }
+ }
+
+ /**
+ * A very simple AccountManagerFuture class
+ * that returns what ever was passed in
+ */
+ private static class MockAccountManagerFuture<T>
+ implements AccountManagerFuture<T> {
+
+ T mResult;
+
+ MockAccountManagerFuture(T result) {
+ mResult = result;
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ public boolean isCancelled() {
+ return false;
+ }
+
+ public boolean isDone() {
+ return true;
+ }
+
+ public T getResult()
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ return mResult;
+ }
+
+ public T getResult(long timeout, TimeUnit unit)
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ return getResult();
+ }
+ }
+}
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index d5f3ce8..b917fbd 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -277,4 +277,21 @@
public final IContentProvider getIContentProvider() {
return mIContentProvider;
}
+
+ /**
+ * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
+ * when directly instantiating the provider for testing.
+ *
+ * <p>Provided for use by {@code android.test.ProviderTestCase2} and
+ * {@code android.test.RenamingDelegatingContext}.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+ @Deprecated
+ public static void attachInfoForTesting(
+ ContentProvider provider, Context context, ProviderInfo providerInfo) {
+ provider.attachInfoForTesting(context, providerInfo);
+ }
}
diff --git a/test-mock/src/android/test/mock/MockService.java b/test-mock/src/android/test/mock/MockService.java
new file mode 100644
index 0000000..dbba4f3
--- /dev/null
+++ b/test-mock/src/android/test/mock/MockService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.test.mock;
+
+import android.app.Application;
+import android.app.Service;
+import android.content.Context;
+
+/**
+ * A mock {@link android.app.Service} class.
+ *
+ * <p>Provided for use by {@code android.test.ServiceTestCase}.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+public class MockService {
+
+ public static <T extends Service> void attachForTesting(Service service, Context context,
+ String serviceClassName,
+ Application application) {
+ service.attach(
+ context,
+ null, // ActivityThread not actually used in Service
+ serviceClassName,
+ null, // token not needed when not talking with the activity manager
+ application,
+ null // mocked services don't talk with the activity manager
+ );
+ }
+
+ private MockService() {
+ }
+}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 706f636..f5c2bc6 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -117,5 +117,20 @@
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
+# Build the android.test.legacy library
+# =====================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.test.legacy
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src/android)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_JAVA_LIBRARIES := android.test.mock.stubs junit
+LOCAL_STATIC_JAVA_LIBRARIES := android.test.base-minus-junit
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
# additionally, build unit tests in a separate .apk
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 0b77c00..6e4c41e 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -17,12 +17,6 @@
package android.test;
import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OnAccountsUpdateListener;
-import android.accounts.OperationCanceledException;
-import android.accounts.Account;
import android.content.ContextWrapper;
import android.content.ContentResolver;
import android.content.Intent;
@@ -32,12 +26,10 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.Handler;
+import android.test.mock.MockAccountManager;
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
import java.util.List;
@@ -52,7 +44,7 @@
public class IsolatedContext extends ContextWrapper {
private ContentResolver mResolver;
- private final MockAccountManager mMockAccountManager;
+ private final AccountManager mMockAccountManager;
private List<Intent> mBroadcastIntents = new ArrayList<>();
@@ -60,7 +52,7 @@
ContentResolver resolver, Context targetContext) {
super(targetContext);
mResolver = resolver;
- mMockAccountManager = new MockAccountManager();
+ mMockAccountManager = MockAccountManager.newMockAccountManager(IsolatedContext.this);
}
/** Returns the list of intents that were broadcast since the last call to this method. */
@@ -123,71 +115,6 @@
return null;
}
- private class MockAccountManager extends AccountManager {
- public MockAccountManager() {
- super(IsolatedContext.this, null /* IAccountManager */, null /* handler */);
- }
-
- public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener,
- Handler handler, boolean updateImmediately) {
- // do nothing
- }
-
- public Account[] getAccounts() {
- return new Account[]{};
- }
-
- public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
- final String type, final String[] features,
- AccountManagerCallback<Account[]> callback, Handler handler) {
- return new MockAccountManagerFuture<Account[]>(new Account[0]);
- }
-
- public String blockingGetAuthToken(Account account, String authTokenType,
- boolean notifyAuthFailure)
- throws OperationCanceledException, IOException, AuthenticatorException {
- return null;
- }
-
-
- /**
- * A very simple AccountManagerFuture class
- * that returns what ever was passed in
- */
- private class MockAccountManagerFuture<T>
- implements AccountManagerFuture<T> {
-
- T mResult;
-
- public MockAccountManagerFuture(T result) {
- mResult = result;
- }
-
- public boolean cancel(boolean mayInterruptIfRunning) {
- return false;
- }
-
- public boolean isCancelled() {
- return false;
- }
-
- public boolean isDone() {
- return true;
- }
-
- public T getResult()
- throws OperationCanceledException, IOException, AuthenticatorException {
- return mResult;
- }
-
- public T getResult(long timeout, TimeUnit unit)
- throws OperationCanceledException, IOException, AuthenticatorException {
- return getResult();
- }
- }
-
- }
-
@Override
public File getFilesDir() {
return new File("/dev/null");
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index 1fa633e..be18b53 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
+import android.test.mock.MockContentProvider;
import android.test.mock.MockContext;
import android.test.mock.MockContentResolver;
import android.database.DatabaseUtils;
@@ -152,7 +153,7 @@
T instance = providerClass.newInstance();
ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = authority;
- instance.attachInfoForTesting(context, providerInfo);
+ MockContentProvider.attachInfoForTesting(instance, context, providerInfo);
return instance;
}
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index fd33321..10ccebc 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -21,6 +21,7 @@
import android.content.ContentProvider;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
+import android.test.mock.MockContentProvider;
import android.util.Log;
import java.io.File;
@@ -71,7 +72,7 @@
if (allowAccessToExistingFilesAndDbs) {
mContext.makeExistingFilesAndDbsAccessible();
}
- mProvider.attachInfoForTesting(mContext, null);
+ MockContentProvider.attachInfoForTesting(mProvider, mContext, null);
return mProvider;
}
diff --git a/test-runner/src/android/test/ServiceTestCase.java b/test-runner/src/android/test/ServiceTestCase.java
index c8ff0f9..cd54955 100644
--- a/test-runner/src/android/test/ServiceTestCase.java
+++ b/test-runner/src/android/test/ServiceTestCase.java
@@ -23,6 +23,7 @@
import android.os.IBinder;
import android.test.mock.MockApplication;
+import android.test.mock.MockService;
import java.util.Random;
/**
@@ -163,14 +164,8 @@
if (getApplication() == null) {
setApplication(new MockApplication());
}
- mService.attach(
- getContext(),
- null, // ActivityThread not actually used in Service
- mServiceClass.getName(),
- null, // token not needed when not talking with the activity manager
- getApplication(),
- null // mocked services don't talk with the activity manager
- );
+ MockService.attachForTesting(
+ mService, getContext(), mServiceClass.getName(), getApplication());
assertNotNull(mService);
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
index 088f322..6e0d58a 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
@@ -40,6 +40,6 @@
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
-LOCAL_NDK_STL_VARIANT := stlport_static
+LOCAL_NDK_STL_VARIANT := c++_static
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/DexLoggerIntegrationTests.java b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
similarity index 91%
rename from tests/DexLoggerIntegrationTests/src/com/android/server/pm/DexLoggerIntegrationTests.java
rename to tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
index d9f34d5..d8b3b20 100644
--- a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/DexLoggerIntegrationTests.java
+++ b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.server.pm;
+package com.android.server.pm.dex;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
import android.util.EventLog;
-
import dalvik.system.DexClassLoader;
import org.junit.After;
@@ -54,14 +54,15 @@
*
* Run with "atest DexLoggerIntegrationTests".
*/
+@LargeTest
@RunWith(JUnit4.class)
public final class DexLoggerIntegrationTests {
- private static final String TAG = DexLoggerIntegrationTests.class.getSimpleName();
-
private static final String PACKAGE_NAME = "com.android.frameworks.dexloggertest";
+ // Event log tag used for SNET related events
private static final int SNET_TAG = 0x534e4554;
+ // Subtag used to distinguish dynamic code loading events
private static final String DCL_SUBTAG = "dcl";
// Obtained via "echo -n copied.jar | sha256sum"
@@ -77,7 +78,8 @@
// Copy the jar from our Java resources to a private data directory
File privateCopy = new File(context.getDir("jars", Context.MODE_PRIVATE), "copied.jar");
- try (InputStream input = DexLoggerIntegrationTests.class.getResourceAsStream("/javalib.jar");
+ Class<?> thisClass = DexLoggerIntegrationTests.class;
+ try (InputStream input = thisClass.getResourceAsStream("/javalib.jar");
OutputStream output = new FileOutputStream(privateCopy)) {
byte[] buffer = new byte[1024];
while (true) {
@@ -112,7 +114,8 @@
// There may already be events in the event log - figure out the most recent one
EventLog.readEvents(tagList, events);
- long previousEventNanos = events.isEmpty() ? 0 : events.get(events.size() - 1).getTimeNanos();
+ long previousEventNanos =
+ events.isEmpty() ? 0 : events.get(events.size() - 1).getTimeNanos();
events.clear();
Process process = Runtime.getRuntime().exec(
diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/NetworkUtilsTest.java
rename to tests/net/java/android/net/NetworkUtilsTest.java
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/tests/net/java/android/net/RouteInfoTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/RouteInfoTest.java
rename to tests/net/java/android/net/RouteInfoTest.java
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 725ddb9..9b75a50 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -35,6 +35,7 @@
import android.net.ip.IpManager;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -62,7 +63,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
@@ -635,7 +635,7 @@
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
IpConnectivityLog log) throws Exception {
- super(config, NetworkInterface.getByName("lo"), ipManagerCallback, log);
+ super(config, InterfaceParams.getByName("lo"), ipManagerCallback, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
diff --git a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
index 54776db..e65585f 100644
--- a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
+++ b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;
+import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -54,8 +55,8 @@
}
IpReachabilityMonitor makeMonitor() {
- return new IpReachabilityMonitor(
- "fake0", 1, mHandler, mLog, mCallback, null, mDependencies);
+ final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
+ return new IpReachabilityMonitor(ifParams, mHandler, mLog, mCallback, null, mDependencies);
}
@Test
diff --git a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
index 38d3d74..f9b7ec8 100644
--- a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
+++ b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.net.MacAddress;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
@@ -36,9 +37,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectivityPacketSummaryTest {
- private static final byte[] MYHWADDR = {
- asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
- };
+ private static final MacAddress MYHWADDR = MacAddress.fromString("80:7a:bf:6f:48:f3");
private String getSummary(String hexBytes) {
hexBytes = hexBytes.replaceAll("\\s+", "");
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
new file mode 100644
index 0000000..21728af
--- /dev/null
+++ b/tests/net/java/android/net/util/InterfaceParamsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InterfaceParamsTest {
+ @Test
+ public void testNullInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName(null));
+ }
+
+ @Test
+ public void testNonExistentInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName("doesnotexist0"));
+ }
+
+ @Test
+ public void testLoopback() {
+ final InterfaceParams ifParams = InterfaceParams.getByName("lo");
+ assertNotNull(ifParams);
+ assertEquals("lo", ifParams.name);
+ assertTrue(ifParams.index > 0);
+ assertNotNull(ifParams.macAddr);
+ assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 113cd37..2b0349c 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -55,14 +55,20 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -116,6 +122,7 @@
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -132,6 +139,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -174,8 +182,11 @@
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
+ private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
+
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
// reflect the state of our test ConnectivityService.
@@ -872,7 +883,7 @@
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
- mock(INetworkManagementService.class),
+ mNetworkManagementService,
mStatsService,
mock(INetworkPolicyManager.class),
mock(IpConnectivityLog.class));
@@ -3489,6 +3500,44 @@
reset(mStatsService);
}
+ @Test
+ public void testBasicDnsConfigurationPushed() throws Exception {
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
+ anyInt(), any(), any(), any(), anyBoolean(), anyString());
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName("test_rmnet_data0");
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ // CS tells netd about the empty DNS config for this network.
+ assertEmpty(mStringArrayCaptor.getValue());
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(1, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 80e42a3..2282c13 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -348,64 +348,6 @@
}
@Test
- public void testCreateInvalidConfigAeadWithAuth() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setAuthentication(direction, AUTH_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on authentication being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testCreateInvalidConfigAeadWithCrypt() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setEncryption(direction, CRYPT_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on encryption being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testCreateInvalidConfigAeadWithAuthAndCrypt() throws Exception {
- IpSecConfig ipSecConfig = new IpSecConfig();
- addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
-
- for (int direction : DIRECTIONS) {
- ipSecConfig.setAuthentication(direction, AUTH_ALGO);
- ipSecConfig.setEncryption(direction, CRYPT_ALGO);
- ipSecConfig.setAuthenticatedEncryption(direction, AEAD_ALGO);
- }
-
- try {
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- fail(
- "IpSecService should have thrown an error on authentication and encryption being"
- + " enabled with authenticated encryption");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
public void testDeleteTransportModeTransform() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 5d1e10e..0467989 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -35,6 +35,8 @@
import android.content.Context;
import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
@@ -76,6 +78,36 @@
private static final InetAddress INADDR_ANY;
+ private static final byte[] AEAD_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x73, 0x61, 0x6C, 0x74
+ };
+ private static final byte[] CRYPT_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ private static final byte[] AUTH_KEY = {
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
+ };
+
+ private static final IpSecAlgorithm AUTH_ALGO =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
+ private static final IpSecAlgorithm CRYPT_ALGO =
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
+ private static final IpSecAlgorithm AEAD_ALGO =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
+
+ private static final int[] DIRECTIONS =
+ new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT};
+
static {
try {
INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
@@ -270,6 +302,127 @@
}
@Test
+ public void testValidateAlgorithmsAuth() {
+ for (int direction : DIRECTIONS) {
+ // Validate that correct algorithm type succeeds
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthentication(direction, AUTH_ALGO);
+ mIpSecService.validateAlgorithms(config, direction);
+
+ // Validate that incorrect algorithm types fails
+ for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) {
+ try {
+ config = new IpSecConfig();
+ config.setAuthentication(direction, algo);
+ mIpSecService.validateAlgorithms(config, direction);
+ fail("Did not throw exception on invalid algorithm type");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsCrypt() {
+ for (int direction : DIRECTIONS) {
+ // Validate that correct algorithm type succeeds
+ IpSecConfig config = new IpSecConfig();
+ config.setEncryption(direction, CRYPT_ALGO);
+ mIpSecService.validateAlgorithms(config, direction);
+
+ // Validate that incorrect algorithm types fails
+ for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) {
+ try {
+ config = new IpSecConfig();
+ config.setEncryption(direction, algo);
+ mIpSecService.validateAlgorithms(config, direction);
+ fail("Did not throw exception on invalid algorithm type");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAead() {
+ for (int direction : DIRECTIONS) {
+ // Validate that correct algorithm type succeeds
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(direction, AEAD_ALGO);
+ mIpSecService.validateAlgorithms(config, direction);
+
+ // Validate that incorrect algorithm types fails
+ for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) {
+ try {
+ config = new IpSecConfig();
+ config.setAuthenticatedEncryption(direction, algo);
+ mIpSecService.validateAlgorithms(config, direction);
+ fail("Did not throw exception on invalid algorithm type");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAuthCrypt() {
+ for (int direction : DIRECTIONS) {
+ // Validate that correct algorithm type succeeds
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthentication(direction, AUTH_ALGO);
+ config.setEncryption(direction, CRYPT_ALGO);
+ mIpSecService.validateAlgorithms(config, direction);
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsNoAlgorithms() {
+ IpSecConfig config = new IpSecConfig();
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; no algorithms specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAeadWithAuth() {
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+ config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; both AEAD and auth algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAeadWithCrypt() {
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+ config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; both AEAD and crypt algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testValidateAlgorithmsAeadWithAuthAndCrypt() {
+ IpSecConfig config = new IpSecConfig();
+ config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+ config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO);
+ config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO);
+ try {
+ mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+ fail("Expected exception; AEAD, auth and crypt algorithm specified");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
public void testDeleteInvalidTransportModeTransform() throws Exception {
try {
mIpSecService.deleteTransportModeTransform(1);
diff --git a/tests/testables/src/android/testing/PollingCheck.java b/tests/testables/src/android/testing/PollingCheck.java
new file mode 100644
index 0000000..5a31450
--- /dev/null
+++ b/tests/testables/src/android/testing/PollingCheck.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.testing;
+
+import junit.framework.Assert;
+import java.util.concurrent.Callable;
+
+public abstract class PollingCheck {
+ private static final long TIME_SLICE = 50;
+ private long mTimeout = 3000;
+
+ public static interface PollingCheckCondition {
+ boolean canProceed();
+ }
+
+ public PollingCheck() {
+ }
+
+ public PollingCheck(long timeout) {
+ mTimeout = timeout;
+ }
+
+ protected abstract boolean check();
+
+ public void run() {
+ if (check()) {
+ return;
+ }
+
+ long timeout = mTimeout;
+ while (timeout > 0) {
+ try {
+ Thread.sleep(TIME_SLICE);
+ } catch (InterruptedException e) {
+ Assert.fail("unexpected InterruptedException");
+ }
+
+ if (check()) {
+ return;
+ }
+
+ timeout -= TIME_SLICE;
+ }
+
+ Assert.fail("unexpected timeout");
+ }
+
+ public static void check(CharSequence message, long timeout, Callable<Boolean> condition)
+ throws Exception {
+ while (timeout > 0) {
+ if (condition.call()) {
+ return;
+ }
+
+ Thread.sleep(TIME_SLICE);
+ timeout -= TIME_SLICE;
+ }
+
+ Assert.fail(message.toString());
+ }
+
+ public static void waitFor(final PollingCheckCondition condition) {
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return condition.canProceed();
+ }
+ }.run();
+ }
+
+ public static void waitFor(long timeout, final PollingCheckCondition condition) {
+ new PollingCheck(timeout) {
+ @Override
+ protected boolean check() {
+ return condition.canProceed();
+ }
+ }.run();
+ }
+}
+
diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h
index 6d2257f..81bcecc 100644
--- a/tools/aapt2/LoadedApk.h
+++ b/tools/aapt2/LoadedApk.h
@@ -42,6 +42,8 @@
// Info about an APK loaded in memory.
class LoadedApk {
public:
+ virtual ~LoadedApk() = default;
+
// Loads both binary and proto APKs from disk.
static std::unique_ptr<LoadedApk> LoadApkFromPath(const ::android::StringPiece& path,
IDiagnostics* diag);
diff --git a/tools/aapt2/filter/AbiFilter.h b/tools/aapt2/filter/AbiFilter.h
index d875cb2..2832711 100644
--- a/tools/aapt2/filter/AbiFilter.h
+++ b/tools/aapt2/filter/AbiFilter.h
@@ -33,6 +33,8 @@
*/
class AbiFilter : public IPathFilter {
public:
+ virtual ~AbiFilter() = default;
+
/** Factory method to create a filter from a list of configuration::Abi. */
static std::unique_ptr<AbiFilter> FromAbiList(const std::vector<configuration::Abi>& abi_list);
diff --git a/tools/aapt2/filter/Filter.h b/tools/aapt2/filter/Filter.h
index d737dc9..f932f9c 100644
--- a/tools/aapt2/filter/Filter.h
+++ b/tools/aapt2/filter/Filter.h
@@ -27,7 +27,7 @@
/** A filter to be applied to a path segment. */
class IPathFilter {
public:
- ~IPathFilter() = default;
+ virtual ~IPathFilter() = default;
/** Returns true if the path should be kept. */
virtual bool Keep(const std::string& path) = 0;
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 102bbf9..e7b269a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -408,6 +408,9 @@
splitAndPrint(s.args());
printf(" NULL),\n");
break;
+ case SECTION_LOG:
+ printf(" new LogSection(%d, %s),\n", field->number(), s.args().c_str());
+ break;
}
}
printf(" NULL };\n");
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 89749fb..bbe6d63 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -166,7 +166,15 @@
attributionDecl.fields.front().name.c_str());
fprintf(out, " event.begin();\n");
for (const auto &chainField : attributionDecl.fields) {
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ fprintf(out, " } else {\n");
+ fprintf(out, " event << \"\";\n");
+ fprintf(out, " }\n");
+ } else {
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ }
}
fprintf(out, " event.end();\n");
fprintf(out, " }\n");
@@ -589,13 +597,18 @@
fprintf(out, " jstring jstr = "
"(jstring)env->GetObjectArrayElement(%s, i);\n",
chainField.name.c_str());
- fprintf(out, " ScopedUtfChars* scoped_%s = "
+ fprintf(out, " if (jstr == NULL) {\n");
+ fprintf(out, " %s_vec.push_back(NULL);\n",
+ chainField.name.c_str());
+ fprintf(out, " } else {\n");
+ fprintf(out, " ScopedUtfChars* scoped_%s = "
"new ScopedUtfChars(env, jstr);\n",
chainField.name.c_str());
- fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
+ fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
chainField.name.c_str(), chainField.name.c_str());
- fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
+ fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
chainField.name.c_str(), chainField.name.c_str());
+ fprintf(out, " }\n");
fprintf(out, " }\n");
}
fprintf(out, "\n");
@@ -648,7 +661,7 @@
fprintf(out, " env->ReleaseIntArrayElements(%s, %s_array, 0);\n",
chainField.name.c_str(), chainField.name.c_str());
} else if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
+ fprintf(out, " for (size_t i = 0; i < scoped_%s_vec.size(); ++i) {\n",
chainField.name.c_str());
fprintf(out, " delete scoped_%s_vec[i];\n", chainField.name.c_str());
fprintf(out, " }\n");
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index b6ad926..eaad137 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -21,7 +21,9 @@
import android.os.Parcelable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Describes information about a detected access point. In addition
@@ -227,6 +229,50 @@
public long seen;
/**
+ * On devices with multiple hardware radio chains, this class provides metadata about
+ * each radio chain that was used to receive this scan result (probe response or beacon).
+ * {@hide}
+ */
+ public static class RadioChainInfo {
+ /** Vendor defined id for a radio chain. */
+ public int id;
+ /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */
+ public int level;
+
+ @Override
+ public String toString() {
+ return "RadioChainInfo: id=" + id + ", level=" + level;
+ }
+
+ @Override
+ public boolean equals(Object otherObj) {
+ if (this == otherObj) {
+ return true;
+ }
+ if (!(otherObj instanceof RadioChainInfo)) {
+ return false;
+ }
+ RadioChainInfo other = (RadioChainInfo) otherObj;
+ return id == other.id && level == other.level;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, level);
+ }
+ };
+
+ /**
+ * Information about the list of the radio chains used to receive this scan result
+ * (probe response or beacon).
+ *
+ * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2
+ * entries based on whether this scan result was received using one or both the chains.
+ * {@hide}
+ */
+ public RadioChainInfo[] radioChainInfos;
+
+ /**
* @hide
* Update RSSI of the scan result
* @param previousRssi
@@ -481,6 +527,7 @@
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -502,6 +549,7 @@
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -530,6 +578,7 @@
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -572,6 +621,7 @@
isCarrierAp = source.isCarrierAp;
carrierApEapType = source.carrierApEapType;
carrierName = source.carrierName;
+ radioChainInfos = source.radioChainInfos;
}
}
@@ -615,6 +665,7 @@
sb.append(", Carrier AP: ").append(isCarrierAp ? "yes" : "no");
sb.append(", Carrier AP EAP Type: ").append(carrierApEapType);
sb.append(", Carrier name: ").append(carrierName);
+ sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
return sb.toString();
}
@@ -687,6 +738,16 @@
dest.writeInt(isCarrierAp ? 1 : 0);
dest.writeInt(carrierApEapType);
dest.writeString(carrierName);
+
+ if (radioChainInfos != null) {
+ dest.writeInt(radioChainInfos.length);
+ for (int i = 0; i < radioChainInfos.length; i++) {
+ dest.writeInt(radioChainInfos[i].id);
+ dest.writeInt(radioChainInfos[i].level);
+ }
+ } else {
+ dest.writeInt(0);
+ }
}
/** Implement the Parcelable interface {@hide} */
@@ -759,6 +820,15 @@
sr.isCarrierAp = in.readInt() != 0;
sr.carrierApEapType = in.readInt();
sr.carrierName = in.readString();
+ n = in.readInt();
+ if (n != 0) {
+ sr.radioChainInfos = new RadioChainInfo[n];
+ for (int i = 0; i < n; i++) {
+ sr.radioChainInfos[i] = new RadioChainInfo();
+ sr.radioChainInfos[i].id = in.readInt();
+ sr.radioChainInfos[i].level = in.readInt();
+ }
+ }
return sr;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3700bdb..70e83db 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -557,14 +557,9 @@
public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
/**
* Broadcast intent action indicating that the state of Wi-Fi connectivity
- * has changed. One extra provides the new state
- * in the form of a {@link android.net.NetworkInfo} object. If the new
- * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
- * the access point.
- * as a {@code String}.
+ * has changed. An extra provides the new state
+ * in the form of a {@link android.net.NetworkInfo} object.
* @see #EXTRA_NETWORK_INFO
- * @see #EXTRA_BSSID
- * @see #EXTRA_WIFI_INFO
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -576,17 +571,16 @@
public static final String EXTRA_NETWORK_INFO = "networkInfo";
/**
* The lookup key for a String giving the BSSID of the access point to which
- * we are connected. Only present when the new state is CONNECTED.
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String)}.
+ * we are connected. No longer used.
*/
+ @Deprecated
public static final String EXTRA_BSSID = "bssid";
/**
* The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
- * information about the access point to which we are connected. Only present
- * when the new state is CONNECTED. Retrieve with
- * {@link android.content.Intent#getParcelableExtra(String)}.
+ * information about the access point to which we are connected.
+ * No longer used.
*/
+ @Deprecated
public static final String EXTRA_WIFI_INFO = "wifiInfo";
/**
* Broadcast intent action indicating that the state of establishing a connection to
@@ -695,11 +689,11 @@
* representing if the scan was successful or not.
* Scans may fail for multiple reasons, these may include:
* <ol>
- * <li>A non-privileged app requested too many scans in a certain period of time.
- * This may lead to additional scan request rejections via "scan throttling".
- * See
- * <a href="https://developer.android.com/preview/features/background-location-limits.html">
- * here</a> for details.
+ * <li>An app requested too many scans in a certain period of time.
+ * This may lead to additional scan request rejections via "scan throttling" for both
+ * foreground and background apps.
+ * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are
+ * exempted from scan throttling.
* </li>
* <li>The device is idle and scanning is disabled.</li>
* <li>Wifi hardware reported a scan failure.</li>
@@ -1596,7 +1590,10 @@
* {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li>
* </ol>
* @return {@code true} if the operation succeeded, i.e., the scan was initiated.
+ * @deprecated The ability for apps to trigger scan requests will be removed in a future
+ * release.
*/
+ @Deprecated
public boolean startScan() {
return startScan(null);
}
@@ -1615,53 +1612,6 @@
}
/**
- * startLocationRestrictedScan()
- * Trigger a scan which will not make use of DFS channels and is thus not suitable for
- * establishing wifi connection.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public boolean startLocationRestrictedScan(WorkSource workSource) {
- return false;
- }
-
- /**
- * Check if the Batched Scan feature is supported.
- *
- * @return false if not supported.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public boolean isBatchedScanSupported() {
- return false;
- }
-
- /**
- * Retrieve the latest batched scan result. This should be called immediately after
- * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public List<BatchedScanResult> getBatchedScanResults() {
- return null;
- }
-
- /**
* Creates a configuration token describing the current network of MIME type
* application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
*
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java
index b4e3097..32f21b9 100644
--- a/wifi/java/android/net/wifi/rtt/RangingRequest.java
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -17,6 +17,7 @@
package android.net.wifi.rtt;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.MacAddress;
import android.net.wifi.ScanResult;
import android.net.wifi.aware.AttachCallback;
@@ -41,8 +42,6 @@
* The ranging request is a batch request - specifying a set of devices (specified using
* {@link RangingRequest.Builder#addAccessPoint(ScanResult)} and
* {@link RangingRequest.Builder#addAccessPoints(List)}).
- *
- * @hide RTT_API
*/
public final class RangingRequest implements Parcelable {
private static final int MAX_PEERS = 10;
@@ -198,7 +197,7 @@
return addResponder(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle));
}
- /*
+ /**
* Add the Responder device specified by the {@link ResponderConfig} to the list of devices
* with which to measure range. The total number of peers added to the request cannot exceed
* the limit specified by {@link #getMaxPeers()}.
@@ -206,8 +205,9 @@
* @param responder Information on the RTT Responder.
* @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
*
- * @hide (SystemApi)
+ * @hide
*/
+ @SystemApi
public Builder addResponder(@NonNull ResponderConfig responder) {
if (responder == null) {
throw new IllegalArgumentException("Null Responder!");
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index a380fae..d5ca8f7 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.MacAddress;
import android.net.wifi.aware.PeerHandle;
import android.os.Handler;
@@ -36,8 +37,6 @@
* <p>
* A ranging result is the distance measurement result for a single device specified in the
* {@link RangingRequest}.
- *
- * @hide RTT_API
*/
public final class RangingResult implements Parcelable {
private static final String TAG = "RangingResult";
@@ -108,6 +107,7 @@
* Will return a {@code null} for results corresponding to requests issued using a {@code
* PeerHandle}, i.e. using the {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)} API.
*/
+ @Nullable
public MacAddress getMacAddress() {
return mMac;
}
@@ -119,7 +119,7 @@
* <p>
* Will return a {@code null} for results corresponding to requests issued using a MAC address.
*/
- public PeerHandle getPeerHandle() {
+ @Nullable public PeerHandle getPeerHandle() {
return mPeerHandle;
}
@@ -182,13 +182,11 @@
return mTimestamp;
}
- /** @hide */
@Override
public int describeContents() {
return 0;
}
- /** @hide */
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mStatus);
@@ -210,7 +208,6 @@
dest.writeLong(mTimestamp);
}
- /** @hide */
public static final Creator<RangingResult> CREATOR = new Creator<RangingResult>() {
@Override
public RangingResult[] newArray(int size) {
diff --git a/wifi/java/android/net/wifi/rtt/RangingResultCallback.java b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
index c8aea3c..9639dc8 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
@@ -17,6 +17,7 @@
package android.net.wifi.rtt;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.os.Handler;
import java.lang.annotation.Retention;
@@ -31,8 +32,6 @@
* peers then the {@link #onRangingResults(List)} will be called with the set of results (@link
* {@link RangingResult}, each of which has its own success/failure code
* {@link RangingResult#getStatus()}.
- *
- * @hide RTT_API
*/
public abstract class RangingResultCallback {
/** @hide */
@@ -68,5 +67,5 @@
*
* @param results List of range measurements, one per requested device.
*/
- public abstract void onRangingResults(List<RangingResult> results);
+ public abstract void onRangingResults(@NonNull List<RangingResult> results);
}
diff --git a/wifi/java/android/net/wifi/rtt/ResponderConfig.java b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
index c3e1007..fb723c5 100644
--- a/wifi/java/android/net/wifi/rtt/ResponderConfig.java
+++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.MacAddress;
import android.net.wifi.ScanResult;
import android.net.wifi.aware.PeerHandle;
@@ -35,8 +36,9 @@
* A Responder configuration may be constructed from a {@link ScanResult} or manually (with the
* data obtained out-of-band from a peer).
*
- * @hide (@SystemApi)
+ * @hide
*/
+@SystemApi
public final class ResponderConfig implements Parcelable {
private static final int AWARE_BAND_2_DISCOVERY_CHANNEL = 2437;
@@ -290,7 +292,7 @@
MacAddress macAddress = MacAddress.fromString(scanResult.BSSID);
int responderType = RESPONDER_AP;
boolean supports80211mc = scanResult.is80211mcResponder();
- int channelWidth = translcateScanResultChannelWidth(scanResult.channelWidth);
+ int channelWidth = translateScanResultChannelWidth(scanResult.channelWidth);
int frequency = scanResult.frequency;
int centerFreq0 = scanResult.centerFreq0;
int centerFreq1 = scanResult.centerFreq1;
@@ -454,7 +456,7 @@
}
/** @hide */
- static int translcateScanResultChannelWidth(int scanResultChannelWidth) {
+ static int translateScanResultChannelWidth(int scanResultChannelWidth) {
switch (scanResultChannelWidth) {
case ScanResult.CHANNEL_WIDTH_20MHZ:
return CHANNEL_WIDTH_20MHZ;
@@ -468,7 +470,7 @@
return CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
default:
throw new IllegalArgumentException(
- "translcateScanResultChannelWidth: bad " + scanResultChannelWidth);
+ "translateScanResultChannelWidth: bad " + scanResultChannelWidth);
}
}
}
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 240b3c1..ec6c46e 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -1,3 +1,19 @@
+/*
+ * 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.net.wifi.rtt;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
@@ -5,6 +21,7 @@
import static android.Manifest.permission.CHANGE_WIFI_STATE;
import static android.Manifest.permission.LOCATION_HARDWARE;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -38,8 +55,6 @@
* changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED}
* broadcast. Note that this broadcast is not sticky - you should register for it and then
* check the above API to avoid a race condition.
- *
- * @hide RTT_API
*/
@SystemService(Context.WIFI_RTT_RANGING_SERVICE)
public class WifiRttManager {
@@ -71,6 +86,8 @@
* Returns the current status of RTT API: whether or not RTT is available. To track
* changes in the state of RTT API register for the
* {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast.
+ * <p>Note: availability of RTT does not mean that the app can use the API. The app's
+ * permissions and platform Location Mode are validated at run-time.
*
* @return A boolean indicating whether the app can use the RTT API at this time (true) or
* not (false).
@@ -95,8 +112,8 @@
* will be used.
*/
@RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
- public void startRanging(RangingRequest request, RangingResultCallback callback,
- @Nullable Handler handler) {
+ public void startRanging(@NonNull RangingRequest request,
+ @NonNull RangingResultCallback callback, @Nullable Handler handler) {
startRanging(null, request, callback, handler);
}
@@ -112,12 +129,13 @@
* callback} object. If a null is provided then the application's main thread
* will be used.
*
- * @hide (@SystemApi)
+ * @hide
*/
+ @SystemApi
@RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
ACCESS_WIFI_STATE})
- public void startRanging(@Nullable WorkSource workSource, RangingRequest request,
- RangingResultCallback callback, @Nullable Handler handler) {
+ public void startRanging(@Nullable WorkSource workSource, @NonNull RangingRequest request,
+ @NonNull RangingResultCallback callback, @Nullable Handler handler) {
if (VDBG) {
Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request
+ ", callback=" + callback + ", handler=" + handler);
@@ -143,10 +161,11 @@
*
* @param workSource The work-sources of the requesters.
*
- * @hide (@SystemApi)
+ * @hide
*/
+ @SystemApi
@RequiresPermission(allOf = {LOCATION_HARDWARE})
- public void cancelRanging(WorkSource workSource) {
+ public void cancelRanging(@Nullable WorkSource workSource) {
if (VDBG) {
Log.v(TAG, "cancelRanging: workSource=" + workSource);
}
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
index a0d407a..11ac058 100644
--- a/wifi/java/android/net/wifi/rtt/package.html
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -13,6 +13,8 @@
<li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
<li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
</ul>
+<p>Usage of the API is also gated by the device's Location Mode: whether it permits Wi-Fi based
+location to be queried.</p>
<p class="note"><strong>Note:</strong> Not all Android-powered devices support Wi-Fi RTT
functionality.
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
new file mode 100644
index 0000000..689ebba
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.net.wifi;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.validateMockitoUsage;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.net.wifi.WifiScanner.ScanSettings;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiScanner}.
+ */
+@SmallTest
+public class ScanResultTest {
+ public static final String TEST_SSID = "\"test_ssid\"";
+ public static final String TEST_BSSID = "04:ac:fe:45:34:10";
+ public static final String TEST_CAPS = "CCMP";
+ public static final int TEST_LEVEL = -56;
+ public static final int TEST_FREQUENCY = 2412;
+ public static final long TEST_TSF = 04660l;
+
+ /**
+ * Setup before tests.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ /**
+ * Clean up after tests.
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ /**
+ * Verify parcel read/write for ScanResult.
+ */
+ @Test
+ public void verifyScanResultParcelWithoutRadioChainInfo() throws Exception {
+ ScanResult writeScanResult = createScanResult();
+ ScanResult readScanResult = parcelReadWrite(writeScanResult);
+ assertScanResultEquals(writeScanResult, readScanResult);
+ }
+
+ /**
+ * Verify parcel read/write for ScanResult.
+ */
+ @Test
+ public void verifyScanResultParcelWithZeroRadioChainInfo() throws Exception {
+ ScanResult writeScanResult = createScanResult();
+ writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[0];
+ ScanResult readScanResult = parcelReadWrite(writeScanResult);
+ assertNull(readScanResult.radioChainInfos);
+ }
+
+ /**
+ * Verify parcel read/write for ScanResult.
+ */
+ @Test
+ public void verifyScanResultParcelWithRadioChainInfo() throws Exception {
+ ScanResult writeScanResult = createScanResult();
+ writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[2];
+ writeScanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo();
+ writeScanResult.radioChainInfos[0].id = 0;
+ writeScanResult.radioChainInfos[0].level = -45;
+ writeScanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo();
+ writeScanResult.radioChainInfos[1].id = 1;
+ writeScanResult.radioChainInfos[1].level = -54;
+ ScanResult readScanResult = parcelReadWrite(writeScanResult);
+ assertScanResultEquals(writeScanResult, readScanResult);
+ }
+
+ /**
+ * Verify copy constructor for ScanResult.
+ */
+ @Test
+ public void verifyScanResultCopyWithoutRadioChainInfo() throws Exception {
+ ScanResult scanResult = createScanResult();
+ ScanResult copyScanResult = new ScanResult(scanResult);
+ assertScanResultEquals(scanResult, copyScanResult);
+ }
+
+ /**
+ * Verify copy constructor for ScanResult.
+ */
+ @Test
+ public void verifyScanResultCopyWithRadioChainInfo() throws Exception {
+ ScanResult scanResult = createScanResult();
+ scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2];
+ scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo();
+ scanResult.radioChainInfos[0].id = 0;
+ scanResult.radioChainInfos[0].level = -45;
+ scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo();
+ scanResult.radioChainInfos[1].id = 1;
+ scanResult.radioChainInfos[1].level = -54;
+ ScanResult copyScanResult = new ScanResult(scanResult);
+ assertScanResultEquals(scanResult, copyScanResult);
+ }
+
+ /**
+ * Verify toString for ScanResult.
+ */
+ @Test
+ public void verifyScanResultToStringWithoutRadioChainInfo() throws Exception {
+ ScanResult scanResult = createScanResult();
+ assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " +
+ "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " +
+ "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " +
+ "80211mcResponder: is not supported, Carrier AP: no, " +
+ "Carrier AP EAP Type: 0, Carrier name: null, " +
+ "Radio Chain Infos: null", scanResult.toString());
+ }
+
+ /**
+ * Verify toString for ScanResult.
+ */
+ @Test
+ public void verifyScanResultToStringWithRadioChainInfo() throws Exception {
+ ScanResult scanResult = createScanResult();
+ scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2];
+ scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo();
+ scanResult.radioChainInfos[0].id = 0;
+ scanResult.radioChainInfos[0].level = -45;
+ scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo();
+ scanResult.radioChainInfos[1].id = 1;
+ scanResult.radioChainInfos[1].level = -54;
+ assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " +
+ "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " +
+ "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " +
+ "80211mcResponder: is not supported, Carrier AP: no, " +
+ "Carrier AP EAP Type: 0, Carrier name: null, " +
+ "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, " +
+ "RadioChainInfo: id=1, level=-54]", scanResult.toString());
+ }
+
+ /**
+ * Write the provided {@link ScanResult} to a parcel and deserialize it.
+ */
+ private static ScanResult parcelReadWrite(ScanResult writeResult) throws Exception {
+ Parcel parcel = Parcel.obtain();
+ writeResult.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ return ScanResult.CREATOR.createFromParcel(parcel);
+ }
+
+ private static ScanResult createScanResult() {
+ ScanResult result = new ScanResult();
+ result.wifiSsid = WifiSsid.createFromAsciiEncoded(TEST_SSID);
+ result.BSSID = TEST_BSSID;
+ result.capabilities = TEST_CAPS;
+ result.level = TEST_LEVEL;
+ result.frequency = TEST_FREQUENCY;
+ result.timestamp = TEST_TSF;
+ return result;
+ }
+
+ private static void assertScanResultEquals(ScanResult expected, ScanResult actual) {
+ assertEquals(expected.SSID, actual.SSID);
+ assertEquals(expected.BSSID, actual.BSSID);
+ assertEquals(expected.capabilities, actual.capabilities);
+ assertEquals(expected.level, actual.level);
+ assertEquals(expected.frequency, actual.frequency);
+ assertEquals(expected.timestamp, actual.timestamp);
+ assertArrayEquals(expected.radioChainInfos, actual.radioChainInfos);
+ }
+}